BZOJ[2827]千山鸟飞绝 线段树

21 篇文章 0 订阅

传送门ber~

一个点跑到一个集合里,不止对自己有影响,也对这个集合中的所有东西有影响
一个一个改显然会炸
不妨打上修改标记,离散化后对每个点开个线段树,有东西加入时打上标记就好了
指针版不写内存回收MLE。。。麻麻我终于会写内存回收啦!

代码如下:

#include<algorithm>
#include<ctype.h>
#include<cstdio>
#include<queue>
#define pii pair<int,int>
#define N 30050
using namespace std;
inline int read(){
    int x=0,f=1;char c;
    do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
    do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
    return x*f;
}
pii b[330050];
struct Data{
    int v,x,y,k,maxw,maxv;
}a[N],q[300010];
struct Node{
    Node *ls,*rs;
    int cnt,maxx;
    int flag1,flag2;
    Node():ls(NULL),rs(NULL),cnt(0),maxx(0),flag1(0),flag2(0){}
    inline void maintain(){
        maxx=0;
        if(ls) maxx=max(maxx,ls->maxx);
        if(rs) maxx=max(maxx,rs->maxx);
        return;
    }
    inline void Pushdown(){
        if(ls) ls->flag1=max(ls->flag1,flag1),ls->flag2=max(ls->flag2,flag2);
        if(rs) rs->flag1=max(rs->flag1,flag1),rs->flag2=max(rs->flag2,flag2);
        flag1=flag2=0;
        return;
    }
}*root[330050];
queue<Node*>q1;
void Delete(Node* tmp){
    if(tmp) q1.push(tmp);
    return;
}
Node* New(){
    if(!q1.empty()){
        Node* tmp=q1.front();q1.pop();
        tmp->ls=tmp->rs=NULL;
        tmp->cnt=tmp->maxx=tmp->flag1=tmp->flag2=0;
        return tmp;
    }
    return new Node;
}
int n,m,top;
void Insert(int L,int R,int x,int v,Node *&k){
    if(!k) k=New();
    k->cnt+=v;
    if(L==R){
        k->maxx=(~v)?a[x].v:0;
        a[x].maxw=max(a[x].maxw,k->flag1);
        a[x].maxv=max(a[x].maxv,k->flag2);
        if(!k->cnt) Delete(k),k=NULL;
        return;
    }
    k->Pushdown();
    int mid=L+R>>1;
    if(x<=mid) Insert(L,mid,x,v,k->ls);
    else Insert(mid+1,R,x,v,k->rs);
    k->maintain();
    if(!k->cnt) Delete(k),k=NULL;
    return;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){
        a[i].v=read();
        a[i].x=read();a[i].y=read();
        b[++top]=pii(a[i].x,a[i].y);
    }
    m=read();
    for(int i=1;i<=m;i++){
        q[i].v=read();q[i].x=read();q[i].y=read();
        b[++top]=pii(q[i].x,q[i].y);
    }
    sort(b+1,b+top+1);
    top=unique(b+1,b+top+1)-b-1;
    for(int i=1;i<=n;i++)
        a[i].k=lower_bound(b+1,b+top+1,pii(a[i].x,a[i].y))-b;
    for(int i=1;i<=m;i++)
        q[i].k=lower_bound(b+1,b+top+1,pii(q[i].x,q[i].y))-b;
    for(int i=1;i<=n;i++){
        if(root[a[i].k]){
            a[i].maxw=max(a[i].maxw,root[a[i].k]->maxx);
            a[i].maxv=max(a[i].maxv,root[a[i].k]->cnt);
            root[a[i].k]->flag1=max(root[a[i].k]->flag1,a[i].v);
            root[a[i].k]->flag2=max(root[a[i].k]->flag2,root[a[i].k]->cnt);
        }
        Insert(1,n,i,1,root[a[i].k]);
    }
    for(int i=1;i<=m;i++){
        Insert(1,n,q[i].v,-1,root[a[q[i].v].k]);
        if(root[q[i].k]){
            a[q[i].v].maxw=max(a[q[i].v].maxw,root[q[i].k]->maxx);
            a[q[i].v].maxv=max(a[q[i].v].maxv,root[q[i].k]->cnt);
            root[q[i].k]->flag1=max(root[q[i].k]->flag1,a[q[i].v].v);
            root[q[i].k]->flag2=max(root[q[i].k]->flag2,root[q[i].k]->cnt);
        }
        Insert(1,n,q[i].v,1,root[a[q[i].v].k=q[i].k]);
    }
    for(int i=1;i<=n;i++) Insert(1,n,i,-1,root[a[i].k]);
    for(int i=1;i<=n;i++)
        printf("%lld\n",1ll*a[i].maxw*a[i].maxv);
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>