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;
}

  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>