HDU 6089 Rikka with Terrorist (线段树)
生活随笔
收集整理的這篇文章主要介紹了
HDU 6089 Rikka with Terrorist (线段树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
http://acm.hdu.edu.cn/showproblem.php?pid=6089
題解
這波強行維護搞得我很懵逼。。。
掃描線,只考慮每個點能走到左上方(不包括正上方,但包括正左方)的哪些點,然后旋轉四次坐標系處理
所有詢問和操作點按照先\(x\)后\(y\)坐標的順序排序,然后枚舉每一行,按\(y\)從小到大的順序枚舉這一行每個點
對于一個詢問點找出前面最后一個操作點,那么要求的就是一個矩形減去一個區間內所有后綴最大值的和
然后這個東西可以用線段樹直接維護,記錄個區間最大值然后pushup的時候二分
操作點就相當于單點修改
時間復雜度\(O(n\log^2n)\).
代碼
#include<cstdio> #include<cstdlib> #include<cstring> #include<utility> #include<algorithm> #define llong long long #define pll pair<llong,llong> #define mkpr make_pair using namespace std;const int N = 1e5;struct SegmentTree {struct SgTNode{llong maxi,psum;} sgt[(N<<2)+3];void clear(int u,int le,int ri){sgt[u].maxi = sgt[u].psum = 0;if(le==ri) return;int mid = (le+ri)>>1;clear(u<<1,le,mid); clear(u<<1|1,mid+1,ri);}llong calc(int u,int le,int ri,llong x){if(le==ri) {return sgt[u].maxi<x ? x : sgt[u].maxi;}int mid = (le+ri)>>1;if(sgt[u<<1|1].maxi<x) {return calc(u<<1,le,mid,x)+x*(ri-mid);}else {return sgt[u].psum-sgt[u<<1|1].psum+calc(u<<1|1,mid+1,ri,x);} //Note here!}void pushup(int u,int le,int ri){int mid = (le+ri)>>1;sgt[u].maxi = max(sgt[u<<1].maxi,sgt[u<<1|1].maxi);sgt[u].psum = calc(u<<1,le,mid,sgt[u<<1|1].maxi)+sgt[u<<1|1].psum;}void modify(int u,int le,int ri,int pos,llong x){if(le==pos && ri==pos) {sgt[u].maxi = sgt[u].psum = x; return;}int mid = (le+ri)>>1;if(pos<=mid) {modify(u<<1,le,mid,pos,x);}else {modify(u<<1|1,mid+1,ri,pos,x);}pushup(u,le,ri);}pll query(int u,int le,int ri,int lb,int rb,llong x){if(lb>rb) {return make_pair(0,0);}if(le>=lb && ri<=rb) {return make_pair(max(sgt[u].maxi,x),calc(u,le,ri,x));}int mid = (le+ri)>>1;if(rb<=mid) {return query(u<<1,le,mid,lb,rb,x);}else if(lb>mid) {return query(u<<1|1,mid+1,ri,lb,rb,x);}else{pll retr = query(u<<1|1,mid+1,ri,lb,rb,x);pll retl = query(u<<1,le,mid,lb,rb,retr.first);return mkpr(retl.first,retl.second+retr.second);}} } sgt;struct Query {int x,y,id;Query() {}Query(int _x,int _y,int _id) {x = _x,y = _y,id = _id;}bool operator <(const Query &arg) const{return x<arg.x || (x==arg.x && y<arg.y);} }; llong fans[N+3]; int mx[N+3];namespace Solve {Query qr[(N<<1)+3];int q;int nx,ny;void addquery(int x,int y,int id) {q++; qr[q] = Query(x,y,id);}void solve(){sort(qr+1,qr+q+1); int j = 1; while(j<=q && qr[j].x==0) j++;for(int i=1; i<=nx; i++){int k = 0;while(j<=q && qr[j].x==i){if(qr[j].id==0){sgt.modify(1,1,ny,qr[j].y,i);k = qr[j].y; mx[qr[j].y] = i;}else{llong ans = (llong)i*(qr[j].y-1-k)-sgt.query(1,1,ny,k+1,qr[j].y-1,mx[qr[j].y]).second; //Note here!fans[qr[j].id] += ans;}j++;}}q = 0; sgt.clear(1,1,ny); for(int i=1; i<=ny; i++) mx[i] = 0ll;} }Query a[N+3],b[N+3]; int nx,ny,m,q;int main() {int T; scanf("%d",&T);while(T--){scanf("%d%d%d%d",&nx,&ny,&m,&q);for(int i=1; i<=m; i++) scanf("%d%d",&a[i].x,&a[i].y);for(int i=1; i<=q; i++) scanf("%d%d",&b[i].x,&b[i].y);//1Solve::nx = nx; Solve::ny = ny;for(int i=1; i<=m; i++) Solve::addquery(a[i].x,a[i].y,0);for(int i=1; i<=q; i++) Solve::addquery(b[i].x,b[i].y,i);Solve::solve();//2Solve::nx = ny; Solve::ny = nx;for(int i=1; i<=m; i++) Solve::addquery(a[i].y,nx+1-a[i].x,0);for(int i=1; i<=q; i++) Solve::addquery(b[i].y,nx+1-b[i].x,i);Solve::solve();//3Solve::nx = nx; Solve::ny = ny;for(int i=1; i<=m; i++) Solve::addquery(nx+1-a[i].x,ny+1-a[i].y,0);for(int i=1; i<=q; i++) Solve::addquery(nx+1-b[i].x,ny+1-b[i].y,i);Solve::solve();//4Solve::nx = ny; Solve::ny = nx;for(int i=1; i<=m; i++) Solve::addquery(ny+1-a[i].y,a[i].x,0);for(int i=1; i<=q; i++) Solve::addquery(ny+1-b[i].y,b[i].x,i);Solve::solve();for(int i=1; i<=q; i++) printf("%lld\n",fans[i]+1);memset(fans,0,sizeof(fans));}return 0; }總結
以上是生活随笔為你收集整理的HDU 6089 Rikka with Terrorist (线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 6136 Death Podra
- 下一篇: AtCoder AGC017C Snuk