luogu1856 [USACO5.5]矩形周長Picture
阿新 • • 發佈:2018-03-03
另一個 UC cstring 線段樹 using sort != 貢獻 tro
看到一坨矩形就要想到掃描線。(poj atantis)
我們把橫邊豎邊分開計算,因為橫邊豎邊其實沒有區別,以下論述全為考慮豎邊的。
怎樣統計一個豎邊對答案的貢獻呢?答:把這個豎邊加入線段樹,當前的總覆蓋長度 減去 加入前的總覆蓋長度 的絕對值 即為這個豎邊的貢獻。
這樣做有一個要求,橫坐標相同的豎邊,要先加進去入邊再刪掉出邊。(為什麽呢?考慮兩個矩形,一個矩形的右邊和另一個矩形的左邊的橫坐標相同但上下錯落)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n, qwq1, pwp1, qwq2, pwp2, cnt, m, num[20005], ans;
struct Line{
int uu, vv, ww, id;
}li1[10005], li2[10005];
bool cmp(Line x, Line y){
if(x.uu!=y.uu) return x.uu<y.uu;
else return x.id>y.id;
}
struct SGT{
int sum[80005], len[80005];
void update(int o, int l, int r, int x, int y, int k){
if(num[l]>=x && num[r]<=y) sum[o] += k;
else{
int mid=(l+r)>>1;
int lson=o<<1;
int rson=lson|1;
if(x<num[mid]) update(lson, l, mid, x, y, k);
if(num[mid]<y) update(rson, mid, r, x, y, k);
}
if (sum[o]>0) len[o] = num[r] - num[l];
else if(l+1==r) len[o] = 0;
else len[o] = len[o<<1] + len[(o<<1)|1];
}
}sgt;
int main(){
cin>>n;
for(int i=-10000; i<=10000; i++) num[++m] = i;
for(int i=1; i<=n; i++){
scanf("%d %d %d %d", &qwq1, &pwp1, &qwq2, &pwp2);
cnt++;
li1[cnt] = (Line){qwq1, pwp1, pwp2, 1};
li2[cnt] = (Line){pwp1, qwq1, qwq2, 1};
cnt++;
li1[cnt] = (Line){qwq2, pwp1, pwp2, -1};
li2[cnt] = (Line){pwp2, qwq1, qwq2, -1};
}
sort(li1+1, li1+1+cnt, cmp);
sort(li2+1, li2+1+cnt, cmp);
for(int i=1; i<=cnt; i++){
int lst=sgt.len[1];
sgt.update(1, 1, m, li1[i].vv, li1[i].ww, li1[i].id);
ans += abs(sgt.len[1]-lst);
}
for(int i=1; i<=cnt; i++){
int lst=sgt.len[1];
sgt.update(1, 1, m, li2[i].vv, li2[i].ww, li2[i].id);
ans += abs(sgt.len[1]-lst);
}
cout<<ans<<endl;
return 0;
}
luogu1856 [USACO5.5]矩形周長Picture