ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021ICPC台北F What a Colorful Wall (扫描线,并查集)

2022-05-08 17:34:55  阅读:208  来源: 互联网

标签:What x1 rta Colorful int x2 扫描线 y1 y2


https://codeforces.com/gym/103443/problem/F
image
image
扫描线核心思想就是从下到上暴力跑一维,把另一维的线段化为两个点处理,若处理两个点的线段的时间复杂度是log,这样平面上n个矩形,值域为X,Y的问题,能够在nXlogn(Y)的复杂度内处理

  • 离散化
  • 暴力一个一个点的涂色是n^3
  • 考虑用扫描线从下往上扫,那么问题就是怎么处理平行x的线段。
  • 因为是颜色覆盖问题,我们倒着处理,那么一段线段[l, r]涂过色后,这段颜色不能再边,扫到这一段时候就要从l直接跳到r。可以想到并查集来实现。
  • 时间复杂度约为 nXlog(Y), (并查集比logn还快一些)
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
//#define int long long
const int N = 1e4 + 5;
const int M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
struct node{
 int x1, y1, x2, y2, c;
} rta[N];
int lisan( vector<int> v, int x ) {
 return lower_bound(v.begin(), v.end(), x) - v.begin();
}
int p[N];
int find ( int x ) { return x == p[x] ? x : p[x] = find(p[x]); }
void merge( int a, int b ) { a = find(a), b = find(b), p[a] = b; }
int main () {
 IOS
 int n; cin >> n;
 vector<int> X, Y;
 //离散化
 for ( int i = 1; i <= n; ++ i ) {
   int x1, y1, x2, y2, c; cin >> x1 >> y1 >> x2 >> y2 >> c;
   rta[i] = { x1, y2, x2, y1, c };
   X.push_back(x1), X.push_back(x2), Y.push_back(y1), Y.push_back(y2);
 }
 sort(X.begin(), X.end()); X.erase( unique(X.begin(), X.end()), X.end());
 sort(Y.begin(), Y.end()); Y.erase ( unique ( Y.begin(), Y.end()), Y.end());
 for ( int i = 1; i <= n; ++ i ) {
   int x1 = lisan(X, rta[i].x1); int x2 = lisan(X, rta[i].x2);
   int y1 = lisan(Y, rta[i].y1); int y2 = lisan(Y, rta[i].y2); int c = rta[i].c;
   rta[i] = { x1, y1, x2, y2, c};
 }
 //离散化后的值域
 int lx = X.size(), ly = Y.size();
 vector<bool> st(n + 1);

 for ( int i = 0; i < ly; ++ i ) {
   for ( int j = 0; j < lx ; ++ j) p[j] = j; // 并查集初始化要大一
   for ( int j = n; j >= 1; -- j ) {
     int x1 = rta[j].x1, x2 = rta[j].x2, y1 = rta[j].y1, y2 = rta[j].y2, c = rta[j].c;
     if( i >= y1 && i < y2) { // 注意根据题目,得出这里比较带不带等号
       for ( int k = find(x1); k < x2; k = find(k) ) {  //跳过已经涂色的
         merge( k, k + 1 ); 
         st[c] = 1;
       }
     }
   }
 }

 cout << count( st.begin(), st.end(), 1 ) << '\n';
 return 0;
}

标签:What,x1,rta,Colorful,int,x2,扫描线,y1,y2
来源: https://www.cnblogs.com/muscletear/p/16246153.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有