BZOJ2827 : 千山鸟飞绝
将坐标离散化后,对于每一个坐标建立一棵动态开节点的线段树,支持查询最大值、和,以及标记下放。
#include<cstdio> #include<algorithm> using namespace std; typedef pair<int,int> P; typedef long long ll; const int N=30010,T=300010; struct Bird{int w,x,y,loc,maxw,maxt;}A[N]; struct Ques{int v,x,y;}B[T]; struct Node{int l,r,taga,tagb,maxw,cnt;}seg[5000000]; P loc[N+T]; int n,m,i,tot; inline void Max(int&a,int b){if(a<b)a=b;} inline void read(int&a){ char c;bool f=0;a=0; while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-'))); if(c!='-')a=c-'0';else f=1; while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0'; if(f)a=-a; } inline int lower(P x){ int l=1,r=n+m,mid,t; while(l<=r)if(loc[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1; return t; } inline void add1(int x,int w,int t){ if(!seg[x].cnt)return; Max(seg[x].taga,w),Max(seg[x].tagb,t); } void add(int x,int a,int b,int c,int d){ seg[x].cnt+=d; if(a==b){ seg[x].maxw=d==1?A[c].w:0; if(d==-1)Max(A[c].maxw,seg[x].taga),Max(A[c].maxt,seg[x].tagb); return; } if(seg[x].taga){ add1(seg[x].l,seg[x].taga,seg[x].tagb),add1(seg[x].r,seg[x].taga,seg[x].tagb); seg[x].taga=seg[x].tagb=0; } int mid=(a+b)>>1; if(c<=mid){ if(!seg[x].l)seg[x].l=++tot; add(seg[x].l,a,mid,c,d); }else{ if(!seg[x].r)seg[x].r=++tot; add(seg[x].r,mid+1,b,c,d); } seg[x].maxw=max(seg[seg[x].l].maxw,seg[seg[x].r].maxw); } inline void fly(int x,int y){ if(seg[y].cnt)Max(A[x].maxw,seg[y].maxw),Max(A[x].maxt,seg[y].cnt); add1(y,A[x].w,seg[y].cnt); add(A[x].loc=y,1,n,x,1); } int main(){ read(n); for(i=1;i<=n;i++)read(A[i].w),read(A[i].x),read(A[i].y),loc[i]=P(A[i].x,A[i].y); read(m); for(i=1;i<=m;i++)read(B[i].v),read(B[i].x),read(B[i].y),loc[n+i]=P(B[i].x,B[i].y); sort(loc+1,loc+n+m+1); tot=n+m; for(i=1;i<=n;i++)fly(i,lower(P(A[i].x,A[i].y))); for(i=1;i<=m;i++)add(A[B[i].v].loc,1,n,B[i].v,-1),fly(B[i].v,lower(P(B[i].x,B[i].y))); for(i=1;i<=n;i++)add(A[i].loc,1,n,i,-1); for(i=1;i<=n;i++)printf("%lld\n",(long long)A[i].maxw*A[i].maxt); return 0; }