POJ - 2482:Stars in Your Window (扫描线 )
题意:二维平面上给你N颗星,给出星星的坐标,亮度; 然后给你一个W*H的窗口,问你最大的亮度和。
思路:扫描线,假设有一个inf*H的窗口,按照y排序,那么就把H范围内的星星放入了这个窗口(单调队列实现),现在就成了华东窗口问题,在一维数组里面找长度为W的窗口的最大和,但是现在带修改,单点修改,固定区间查询,怎么做呢? 和学生讨论了一下,常规的很难实现。 我们需要转化一下,把单点修改转化为区间修改,然后单点查询最大值。 如果x处插入L,则[x,Rx]区间加x。 ans=max(mx[1]);
(可以出一道,待修改的滑动窗口问题。
#include<iostream> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=40010; struct in{ int x,y,l; bool friend operator <(in w,in v){ return w.y<v.y; } }s[maxn]; int ans,W,H,lazy[maxn],mx[maxn]; int b[maxn],tot,p[maxn]; void pushdown(int Now) { if(!lazy[Now]) return ; lazy[Now<<1]+=lazy[Now]; lazy[Now<<1|1]+=lazy[Now]; mx[Now<<1]+=lazy[Now]; mx[Now<<1|1]+=lazy[Now]; lazy[Now]=0; } void add(int Now,int L,int R,int l,int r,int val) { if(l<=L&&r>=R){ mx[Now]+=val; lazy[Now]+=val; return ; } pushdown(Now); int Mid=(L+R)>>1; if(l<=Mid) add(Now<<1,L,Mid,l,r,val); if(r>Mid) add(Now<<1|1,Mid+1,R,l,r,val); mx[Now]=max(mx[Now<<1],mx[Now<<1|1]); } int main() { int T,N; while(~scanf("%d%d%d",&N,&W,&H)){ ans=0; tot=0; rep(i,1,N) scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].l); sort(s+1,s+N+1); rep(i,1,N<<2) lazy[i]=mx[i]=0; rep(i,1,N) b[++tot]=s[i].x; sort(b+1,b+N+1); tot=unique(b+1,b+N+1)-(b+1); rep(i,1,N) s[i].x=lower_bound(b+1,b+tot+1,s[i].x)-b; int R=1; rep(i,1,tot) { while(R+1<=tot&&b[R+1]-b[i]+1<=W) R++; p[i]=R; } for(int i=1,j=1;i<=N;i++){ add(1,1,tot,s[i].x,p[s[i].x],s[i].l); while(j<=i&&s[i].y-s[j].y+1>H) { add(1,1,tot,s[j].x,p[s[j].x],-s[j].l); j++; } ans=max(ans,mx[1]); } printf("%d\n",ans); } return 0; }
It is your time to fight!