将坐标离散化后,对于每一个坐标建立一棵动态开节点的线段树,支持查询最大值、和,以及标记下放。
#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;
}