Codeforces702F. T-Shirts

一道很好的idea題
一開始想過合併 但是總感覺合併的複雜度太大
然後發現其實每個元素被合併次數是可以做到log(109) 次的

然後就可以直接暴力插入 複雜度是nlog(n×109)
用重量平衡樹維護一下
其實不算可持久化 但不想另開一個分類了QaQ

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<set>
using namespace std;

char c;
inline void read(int&a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}


struct Node
{
    int Optag,anstag,ans,Rnd,Op,no;
    Node*lc,*rc;
    Node(){lc=rc=NULL;Optag=anstag=ans=Rnd=Op=no=0;}
}*Empty=new Node;

inline void add(Node*a,int Op,int ans)
{a->ans+=ans,a->Op+=Op;a->Optag+=Op,a->anstag+=ans;}

inline void push(Node*a)
{
    if(!a->Optag)return;
    add(a->lc,a->Optag,a->anstag);
    add(a->rc,a->Optag,a->anstag);
    a->Optag=a->anstag=0;
}
// l<c r>=c
Node *Split(Node*Root,Node *&l,Node*&r,int c)
{
    if(Root==Empty)return l=r=Empty;
    Node*L,*R;
    push(Root);
    if(Root->Op<c)
    {
        Split(Root->rc,L,R,c);
        l=Root;
        l->rc=L;
        return r=R;
    }
    else
    {
        Split(Root->lc,L,R,c);
        r=Root;
        r->lc=R;
        return l=L;
    }
}
//a<=b
Node *Merge(Node *a,Node *b)
{
    if(a==Empty)return b;
    else if(b==Empty)return a;
    push(a),push(b);
    if(a->Rnd>b->Rnd)return a->rc=Merge(a->rc,b),a;
    else return b->lc=Merge(a,b->lc),b;
}
pair<int,int>L[1000001],R[1000001];
Node A[1000001];

int Right(Node*a)
{
    if(a==Empty)return -1000;
    push(a);
    return a->rc!=Empty?Right(a->rc):a->Op;
}

int Left(Node*a)
{
    if(a==Empty)return 2000000000;
    push(a);
    return a->lc!=Empty?Left(a->lc):a->Op;
}
int Ans[1000001];
void Re(Node*a)
{
    if(a==Empty)return;
    push(a);
    Ans[a->no]=a->ans;
    Re(a->lc),Re(a->rc);
}
int main()
{
    int cnt=0;
    int n,m;
    read(n);
    for(int i=1;i<=n;i++)
    {
        int u,v;
        read(u),read(v);
        L[i]=make_pair(-v,u);
    }
    sort(L+1,L+1+n),read(m);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        read(u);
        R[i]=make_pair(u,i);
    }
    sort(R+1,R+1+m);
    Node *Root=Empty;
    for(int i=1;i<=m;i++)
    {
        A[i].Rnd=rand()*rand();
        A[i].Op=R[i].first;
        A[i].lc=A[i].rc=Empty;
        A[i].no=R[i].second;
        Root=Merge(Root,A+i);
    }
    for(int i=1;i<=n;i++)
    {
        int C=L[i].second;
        Node *LT,*RT;
        Split(Root,LT,RT,C);
        if(LT==Empty)
        {
            add(Root=RT,-C,1);
            continue;
        }
        if(RT==Empty){Root=LT;continue;}
        add(RT,-C,1);
        int l=Right(LT),r=Left(RT);
        while(l>r)
        {

            Node *LL,*LR,*RL,*RR;
            Split(LT,LL,LR,r+1);
            Split(RT,RL,RR,r+1);
            RT=RR;
            LT=Merge(Merge(LL,RL),LR);
            l=Right(LT);
            r=Left(RT);
        }
        Root=Merge(LT,RT);
    }
    Re(Root);
    for(int i=1;i<=m;i++)
        printf("%d ",Ans[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章