洛谷 P2824 [HEOI2016/TJOI2016]排序 (线段树合并)

题解中有一种思路很高妙而且看上去可以适用一些其他情况的离线方法


线段树合并&复杂度的简单说明:https://blog.csdn.net/zawedx/article/details/51818475

调用一次合并函数的时间是常数,
而合并函数每调用一次就会删掉一个点,
所以合并的总代价为删掉的点数和,

或者理解为:

https://wenku.baidu.com/view/88f4e134e518964bcf847c95.html

所以好像要合并就不能可持久化?(指保留每一个版本,在合并后仍旧保留合并前的版本)(未确定)

错误记录:空间开成O(n),

没删调试信息的代码:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<set>
  4 using namespace std;
  5 int n,m;
  6 namespace SegT
  7 {
  8 const int N=600000;
  9 int lc[N],rc[N],dat[N];
 10 int st[N+10];int top;
 11 void init()    {for(int i=N-1;i>=1;i--)st[++top]=i;}
 12 int getnode()    {int t=st[top--];lc[t]=rc[t]=dat[t]=0;return t;}
 13 void delnode(int x)    {st[++top]=x;}
 14 #define mid (l+((r-l)>>1))
 15 int L,x;
 16 void _addx(int l,int r,int &num)
 17 {
 18     if(!num)    num=getnode();
 19     if(l==r)    {dat[num]+=x;return;}
 20     if(L<=mid)    _addx(l,mid,lc[num]);
 21     else    _addx(mid+1,r,rc[num]);
 22     dat[num]=dat[lc[num]]+dat[rc[num]];
 23 }
 24 void addx(int pos,int &num)    {L=pos;x=1;_addx(1,n,num);}
 25 void split(int l,int r,int &num,int &x,int k)
 26 //当前区间为[l,r],将num中的前k小拆出来,放到x中
 27 {
 28     //assert(dat[num]>=k&&k>0);
 29     if(!k)    return;
 30     if(!x)    x=getnode();
 31     if(l==r)    {dat[num]-=k;dat[x]+=k;return;}
 32     int t=dat[lc[num]];
 33     if(t>k)    split(l,mid,lc[num],lc[x],k);
 34     else    lc[x]=lc[num],lc[num]=0;
 35     if(t<k)    split(mid+1,r,rc[num],rc[x],k-t);
 36     dat[num]=dat[lc[num]]+dat[rc[num]];
 37     dat[x]=dat[lc[x]]+dat[rc[x]];
 38 }
 39 int merge(/*int l,int r,*/int num,int x)
 40 //将x和num并起来
 41 {
 42     if(!x||!num)    return x+num;
 43     //if(l==r)    {dat[num]+=dat[x];delnode(x);return;}
 44     lc[num]=merge(lc[num],lc[x]);
 45     rc[num]=merge(rc[num],rc[x]);
 46     dat[num]+=dat[x];
 47     delnode(x);
 48     return num;
 49 //    if(!lc[num]||!lc[x])    lc[num]=lc[num]+lc[x];
 50 //    else    merge(l,mid,lc[num],lc[x]);
 51 //    if(!rc[num]||!rc[x])    rc[num]=rc[num]+rc[x];
 52 //    else    merge(mid+1,r,rc[num],rc[x]);
 53 //    dat[num]=dat[lc[num]]+dat[rc[num]];
 54 //    delnode(x);
 55 }
 56 int _query_kth(int l,int r,int k,int num)
 57 {
 58     if(l==r)    return l;
 59     if(dat[lc[num]]>=k)    return _query_kth(l,mid,k,lc[num]);
 60     else    return _query_kth(mid+1,r,k-dat[lc[num]],rc[num]);
 61 }
 62 int query_kth(int k,int num)
 63 {
 64     return _query_kth(1,n,k,num);
 65 }
 66 #undef mid
 67 }
 68 struct Dat
 69 {
 70     int r,l,nd,type;//type=0升序,type=1降序
 71 };
 72 bool operator<(const Dat &a,const Dat &b)
 73 {
 74     return a.r<b.r||(a.r==b.r&&a.l<b.l);
 75 }
 76 set<Dat> s;
 77 int split_node(int l,int r)
 78 {
 79     int ansn=0,tn;Dat t;
 80     auto it=s.lower_bound((Dat){l,0,0,0});
 81     if(it->l!=l)
 82     {
 83         t=*it;s.erase(it);tn=0;
 84         if(t.type==0)
 85         {
 86             SegT::split(1,n,t.nd,tn,l-t.l);
 87             s.insert((Dat){l-1,t.l,tn,0});
 88             //ansn=SegT::merge(ansn,t.nd);
 89             s.insert((Dat){t.r,l,t.nd,0});
 90         }
 91         else
 92         {
 93             SegT::split(1,n,t.nd,tn,t.r-l+1);
 94             s.insert((Dat){l-1,t.l,t.nd,1});
 95             //ansn=SegT::merge(ansn,tn);
 96             s.insert((Dat){t.r,l,tn,1});
 97         }
 98     }
 99     it=s.lower_bound((Dat){r,0,0,0});
100     if(it->r!=r)
101     {
102         t=*it;s.erase(it);tn=0;
103         if(t.type==0)
104         {
105             SegT::split(1,n,t.nd,tn,r-t.l+1);
106             s.insert((Dat){t.r,r+1,t.nd,0});
107             //ansn=SegT::merge(ansn,tn);
108             s.insert((Dat){r,t.l,tn,0});
109         }
110         else
111         {
112             SegT::split(1,n,t.nd,tn,t.r-r);
113             s.insert((Dat){t.r,r+1,tn,1});
114             //ansn=SegT::merge(ansn,t.nd);
115             s.insert((Dat){r,t.l,t.nd,1});
116         }
117     }
118     while(1)
119     {
120         it=s.lower_bound((Dat){l,0,0,0});
121         if(it==s.end()||it->l>r)    break;
122         t=*it;s.erase(it);
123         ansn=SegT::merge(ansn,t.nd);
124     }
125     return ansn;
126 }
127 //void out()
128 //{
129 //    for(auto i : s)
130 //    {
131 //        printf("a%d %d %d %d\n",i.r,i.l,i.nd,i.type);
132 //    }
133 //}
134 int main()
135 {
136     SegT::init();
137     int t,t2,i,idx,l,r,q;
138     scanf("%d%d",&n,&m);
139     for(i=1;i<=n;i++)
140     {
141         scanf("%d",&t);
142         t2=SegT::getnode();
143         SegT::addx(t,t2);
144         s.insert((Dat){i,i,t2,0});
145     }
146     while(m--)
147     {
148         scanf("%d%d%d",&idx,&l,&r);
149         t=split_node(l,r);
150         s.insert((Dat){r,l,t,idx});
151     }
152     scanf("%d",&q);
153     t=split_node(q,q);
154     printf("%d",SegT::query_kth(1,t));
155     return 0;
156 }
View Code

删了一些奇怪调试代码之后的代码:

  1 #pragma GCC optimize("Ofast")
  2 #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
  3 #pragma GCC diagnostic error "-fwhole-program"
  4 #pragma GCC diagnostic error "-fcse-skip-blocks"
  5 #pragma GCC diagnostic error "-funsafe-loop-optimizations"
  6 #pragma GCC diagnostic error "-std=c++14"
  7 #include<cstdio>
  8 #include<algorithm>
  9 #include<set>
 10 using namespace std;
 11 int n,m;
 12 namespace SegT
 13 {
 14 const int N=600000;
 15 int lc[N],rc[N],dat[N];
 16 int st[N+10];int top;
 17 void init()    {for(int i=N-1;i>=1;i--)st[++top]=i;}
 18 int getnode()    {int t=st[top--];lc[t]=rc[t]=dat[t]=0;return t;}
 19 void delnode(int x)    {st[++top]=x;}
 20 #define mid (l+((r-l)>>1))
 21 int L,x;
 22 void _addx(int l,int r,int &num)
 23 {
 24     if(!num)    num=getnode();
 25     if(l==r)    {dat[num]+=x;return;}
 26     if(L<=mid)    _addx(l,mid,lc[num]);
 27     else    _addx(mid+1,r,rc[num]);
 28     dat[num]=dat[lc[num]]+dat[rc[num]];
 29 }
 30 void addx(int pos,int &num)    {L=pos;x=1;_addx(1,n,num);}
 31 void split(int l,int r,int &num,int &x,int k)
 32 //当前区间为[l,r],将num中的前k小拆出来,放到x中
 33 {
 34     if(!k)    return;
 35     if(!x)    x=getnode();
 36     if(l==r)    {dat[num]-=k;dat[x]+=k;return;}
 37     int t=dat[lc[num]];
 38     if(t>k)    split(l,mid,lc[num],lc[x],k);
 39     else    lc[x]=lc[num],lc[num]=0;
 40     if(t<k)    split(mid+1,r,rc[num],rc[x],k-t);
 41     dat[num]=dat[lc[num]]+dat[rc[num]];
 42     dat[x]=dat[lc[x]]+dat[rc[x]];
 43 }
 44 int merge(int num,int x)
 45 //将x和num并起来
 46 {
 47     if(!x||!num)    return x+num;
 48     //if(l==r)    {dat[num]+=dat[x];delnode(x);return;}//不用判的
 49     lc[num]=merge(lc[num],lc[x]);
 50     rc[num]=merge(rc[num],rc[x]);
 51     dat[num]+=dat[x];
 52     delnode(x);
 53     return num;
 54 }
 55 int _query_kth(int l,int r,int k,int num)
 56 {
 57     if(l==r)    return l;
 58     if(dat[lc[num]]>=k)    return _query_kth(l,mid,k,lc[num]);
 59     else    return _query_kth(mid+1,r,k-dat[lc[num]],rc[num]);
 60 }
 61 int query_kth(int k,int num)
 62 {
 63     return _query_kth(1,n,k,num);
 64 }
 65 #undef mid
 66 }
 67 struct Dat
 68 {
 69     int r,l,nd,type;//type=0升序,type=1降序
 70 };
 71 bool operator<(const Dat &a,const Dat &b)
 72 {
 73     return a.r<b.r||(a.r==b.r&&a.l<b.l);
 74 }
 75 set<Dat> s;
 76 int split_node(int l,int r)
 77 {
 78     int ansn=0,tn;Dat t;
 79     auto it=s.lower_bound((Dat){l,0,0,0});
 80     if(it->l!=l)
 81     {
 82         t=*it;s.erase(it);tn=0;
 83         if(t.type==0)
 84         {
 85             SegT::split(1,n,t.nd,tn,l-t.l);
 86             s.insert((Dat){l-1,t.l,tn,0});
 87             s.insert((Dat){t.r,l,t.nd,0});
 88         }
 89         else
 90         {
 91             SegT::split(1,n,t.nd,tn,t.r-l+1);
 92             s.insert((Dat){l-1,t.l,t.nd,1});
 93             s.insert((Dat){t.r,l,tn,1});
 94         }
 95     }
 96     it=s.lower_bound((Dat){r,0,0,0});
 97     if(it->r!=r)
 98     {
 99         t=*it;s.erase(it);tn=0;
100         if(t.type==0)
101         {
102             SegT::split(1,n,t.nd,tn,r-t.l+1);
103             s.insert((Dat){t.r,r+1,t.nd,0});
104             s.insert((Dat){r,t.l,tn,0});
105         }
106         else
107         {
108             SegT::split(1,n,t.nd,tn,t.r-r);
109             s.insert((Dat){t.r,r+1,tn,1});
110             s.insert((Dat){r,t.l,t.nd,1});
111         }
112     }
113     while(1)
114     {
115         it=s.lower_bound((Dat){l,0,0,0});
116         if(it==s.end()||it->l>r)    break;
117         t=*it;s.erase(it);
118         ansn=SegT::merge(ansn,t.nd);
119     }
120     return ansn;
121 }
122 int main()
123 {
124     SegT::init();
125     int t,t2,i,idx,l,r,q;
126     scanf("%d%d",&n,&m);
127     for(i=1;i<=n;i++)
128     {
129         scanf("%d",&t);
130         t2=SegT::getnode();
131         SegT::addx(t,t2);
132         s.insert((Dat){i,i,t2,0});
133     }
134     while(m--)
135     {
136         scanf("%d%d%d",&idx,&l,&r);
137         t=split_node(l,r);
138         s.insert((Dat){r,l,t,idx});
139     }
140     scanf("%d",&q);
141     t=split_node(q,q);
142     printf("%d",SegT::query_kth(1,t));
143     return 0;
144 }

猜你喜欢

转载自www.cnblogs.com/hehe54321/p/8906489.html