luoguP5490扫描线

扫描线板子题。注意两倍数组(不太清楚原理)

一位大佬的博客:https://blog.csdn.net/qq_38786088/article/details/78633478,讲的太好了。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 
 5 using namespace std;
 6 typedef long long ll;
 7 
 8 const int Maxn = 2e5+10;
 9 
10 ll read(){
11     ll ans = 0;char last = ' ',ch = getchar();
12     while(ch < '0'||ch > '9')last = ch,ch = getchar();
13     while('0' <= ch&&ch <= '9')ans = ans*10+ch-'0',ch = getchar();
14     if(last == '-')return -ans;return ans;
15 }
16 
17 struct node{
18     ll x,y1,y2,k;
19     bool operator <(const node& asdf)const{
20         return x < asdf.x;
21     }
22 }rem[Maxn<<1];
23 
24 ll ans,n,tot1,tot2,cnt,x1,y1,x2,y2;
25 ll pos[Maxn<<1],a[Maxn<<1],cov[Maxn<<2],len[Maxn<<2];
26 
27 void pushup(ll p,ll s,int t){
28     if(cov[p])len[p] = pos[t+1]-pos[s];//??
29     else if(s == t)len[p] = 0;
30     else len[p] = len[p<<1]+len[p<<1|1];
31 }
32 
33 void update(ll L,ll R,ll s,ll t,ll p,ll k){
34     if(L <= s&&t <= R){cov[p] += k;pushup(p,s,t);return;}
35     ll mid = s+t>>1;
36     if(L <= mid)update(L,R,s,mid,p<<1,k);
37     if(mid < R)update(L,R,mid+1,t,p<<1|1,k);
38     pushup(p,s,t);
39 }
40 
41 int main(){
42     n = read();
43     for(int i = 1;i <= n;i++){
44         x1 = read(),y1 = read(),x2 = read(),y2 = read();
45         a[++tot1] = y1,a[++tot1] = y2;
46         rem[++tot2].x = x1,rem[tot2].y1 = y1,rem[tot2].y2 = y2,rem[tot2].k = 1;
47         rem[++tot2].x = x2,rem[tot2].y1 = y1,rem[tot2].y2 = y2,rem[tot2].k = -1;
48     }
49     sort(a+1,a+tot1+1);
50     for(int i = 1;i <= tot1;i++)if(a[i] != a[i-1]||i == 1)pos[++cnt] = a[i];
51     sort(rem+1,rem+tot2+1);
52     for(int i = 1;i < tot2;i++){
53         ll L = lower_bound(pos+1,pos+cnt+1,rem[i].y1)-pos;
54         ll R = lower_bound(pos+1,pos+cnt+1,rem[i].y2)-pos;
55         update(L,R-1,1,cnt,1,rem[i].k);
56         ans += len[1]*(rem[i+1].x-rem[i].x);
57     }
58     cout << ans;
59 return 0;
60 }

猜你喜欢

转载自www.cnblogs.com/Wangsheng5/p/11623019.html