【学习笔记】splay 发表于 2018-05-09 splay是个好东西复杂度O(nlogn)(势能分析我不会)常数较大请写迭代每次询问后都要做splay操作(一直询问深度为O(n)的点就挂了,例如依次插入1到n)一个常数不太大的模板123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253#include<bits/stdc++.h>#define mp make_pair#define pb push_backusing namespace std;typedef long long LL;typedef pair<int,int> PII;inline LL read(){ LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;}const int N=100008;int n;int opt,x;int tot,rt,ch[N][2],fa[N],key[N],num[N],sum[N];inline void newnode(int &pos,int p,int x){ pos=++tot; fa[pos]=p; key[pos]=x; num[pos]=sum[pos]=1; ch[pos][0]=ch[pos][1]=0;}inline void pushup(int x){ sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+num[x];}inline void rotate(int x,int op){ int y=fa[x]; ch[y][!op]=ch[x][op]; fa[ch[x][op]]=y; if(fa[y]){ ch[fa[y]][ch[fa[y]][1]==y]=x; } fa[x]=fa[y]; ch[x][op]=y; fa[y]=x; pushup(y); pushup(x); }inline void splay(int x,int goal){ while(fa[x]!=goal){ if(fa[fa[x]]==goal){ rotate(x,ch[fa[x]][0]==x); } else{ int y=fa[x]; bool op=ch[fa[y]][0]==y; if(ch[y][op]==x){ rotate(x,!op); rotate(x,op); } else{ rotate(y,op); rotate(x,op); } } } if(goal==0){ rt=x; }}inline void insert(int x){ if(rt==0){ newnode(rt,0,x); return; } int tmp=rt; while(1){ if(key[tmp]==x){ ++num[tmp]; splay(tmp,0); return; } if(ch[tmp][key[tmp]<x]==0) break; tmp=ch[tmp][key[tmp]<x]; } newnode(ch[tmp][key[tmp]<x],tmp,x); splay(tot,0); return;}inline bool find(int x){ int tmp=rt; while(tmp){ if(key[tmp]==x){ splay(tmp,0); return 1; } if(key[tmp]>x){ tmp=ch[tmp][0]; } else{ tmp=ch[tmp][1]; } } return 0;}inline void pop(){ if(num[rt]>1){ --num[rt];--sum[rt];return; } if(!ch[rt][0]){ fa[ch[rt][1]]=0; rt=ch[rt][1]; return; } if(!ch[rt][1]){ fa[ch[rt][0]]=0; rt=ch[rt][0]; return; } int tmp=ch[rt][0]; while(ch[tmp][1]) tmp=ch[tmp][1]; splay(tmp,rt); ch[tmp][1]=ch[rt][1]; rt=tmp; fa[tmp]=0; fa[ch[rt][1]]=rt; pushup(rt);}inline void del(int x){ if(find(x)){ pop(); } }inline int get_pre(int x){ int tmp=rt,ans=INT_MIN; while(1){ if(key[tmp]<x){ ans=max(ans,key[tmp]); if(!ch[tmp][1]){ splay(tmp,0); break; } tmp=ch[tmp][1]; } else{ if(!ch[tmp][0]){ splay(tmp,0); break; } tmp=ch[tmp][0]; } } return ans;}inline int get_nxt(int x){ int tmp=rt,ans=INT_MAX; while(1){ if(key[tmp]>x){ ans=min(ans,key[tmp]); if(!ch[tmp][0]){ splay(tmp,0); break; } tmp=ch[tmp][0]; } else{ if(!ch[tmp][1]){ splay(tmp,0); break; } tmp=ch[tmp][1]; } } return ans;}inline int rank(int x){ int tmp=rt,ans=0; while(1){ if(key[tmp]>=x){ if(!ch[tmp][0]){ splay(tmp,0); break; } tmp=ch[tmp][0]; } else{ ans+=sum[ch[tmp][0]]+num[tmp]; if(!ch[tmp][1]){ splay(tmp,0); break; } tmp=ch[tmp][1]; } } return ans+1;}inline int kth(int x){ int tmp=rt; while(x){ if(sum[ch[tmp][0]]>=x){ tmp=ch[tmp][0]; } else{ x-=sum[ch[tmp][0]]; if(x<=num[tmp]){ splay(tmp,0); return key[tmp]; } x-=num[tmp]; tmp=ch[tmp][1]; } }}int main(){ n=read(); for(int i=1;i<=n;++i){ opt=read();x=read(); switch (opt){ case 1:{ insert(x); break; } case 2:{ del(x); break; } case 3:{ printf("%d\n",rank(x)); break; } case 4:{ printf("%d\n",kth(x)); break; } case 5:{ printf("%d\n",get_pre(x)); break; } case 6:{ printf("%d\n",get_nxt(x)); break; } } } return 0;} splay最特色的区间翻转123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133#include<bits/stdc++.h>#define mp make_pair#define pb push_backusing namespace std;typedef long long LL;typedef pair<int,int> PII;inline LL read(){ LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;}const int N=100008;int n,m;int l,r,rt,tot;int fa[N],sz[N],ch[N][2];bool rev[N];inline void pushup(int x){ sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}inline void rotate(int x,int op){ int y=fa[x]; ch[y][!op]=ch[x][op]; fa[ch[x][op]]=y; if(fa[y]){ ch[fa[y]][ch[fa[y]][1]==y]=x; } fa[x]=fa[y]; ch[x][op]=y; fa[y]=x; pushup(y); pushup(x);}inline void splay(int x,int goal){ while(fa[x]!=goal){ if(fa[fa[x]]==goal){ rotate(x,ch[fa[x]][0]==x); } else{ int y=fa[x]; bool op=ch[fa[y]][0]==y; if(ch[y][op]==x){ rotate(x,!op); rotate(x,op); } else{ rotate(y,op); rotate(x,op); } } } if(goal==0){ rt=x; }}inline void pushdown(int x){ if(rev[x]){ swap(ch[x][0],ch[x][1]); rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; rev[x]=0; }}inline int find(int x){ int tmp=rt,cnt=0; while(1){ pushdown(tmp); if(sz[ch[tmp][0]]+1==x) return tmp; if(sz[ch[tmp][0]]>=x){ tmp=ch[tmp][0]; } else{ x-=sz[ch[tmp][0]]+1; tmp=ch[tmp][1]; } }}inline void rever(int l,int r){ int x=find(l-1),y=find(r+1); splay(x,0); splay(y,rt); rev[ch[y][0]]^=1;}inline void build(int p,int l,int r){ if(l>r) return; if(l==r){ fa[l]=p; sz[l]=1; if(l<p){ ch[p][0]=l; } else{ ch[p][1]=l; } return; } int mid=(l+r)>>1; fa[mid]=p; build(mid,l,mid-1); build(mid,mid+1,r); pushup(mid); if(mid<p){ ch[p][0]=mid; } else{ ch[p][1]=mid; }}int main(){ n=read();m=read(); build(0,1,n+2); rt=(n+3)>>1; while(m--){ l=read()+1;r=read()+1; if(l==r) continue; rever(l,r); } //不能print!!有标记还没下放!! for(int i=2;i<=n+1;++i){ printf("%d ",find(i)-1); } return 0;}
poj2985The k-th Largest Group 发表于 2018-05-07 123456单点修改找第k大二分+树状数组,复杂度O(nlog^2n)树状数组上二分,复杂度O(nlogn)妙极了树状数组二分和线段树二分差不多 阅读全文 »
luogu1903 [国家集训队]数颜色 发表于 2018-05-02 1234567891011带修改的莫队设块长为blk则复杂度为O(n*blk+n*n/blk+(n/blk)*(n/blk)*n)均值求出blk=n^(2/3)总复杂度为O(n^5/3)排序的时候一定要求出每个点所属的块不要用除法!不要用除法!不要用除法!(t到死) 阅读全文 »
luogu2709 小B的询问 发表于 2018-05-01 1234567关于排序的速度:cmp<重载<友元重载(部分数据即实验结果)莫队裸题小优化:对奇数块,r从小到大对偶数快,r从大到小 阅读全文 »
luogu1198 [JSOI2008]最大数 发表于 2018-04-30 1234567做法很多把板子复习一下1.单调队列,然后二分2.单调队列,然后维护每个位置的更优解,加上路径压缩3.树状数组,需要从后往前加,最大值不能作减法4.线段树5.分块 阅读全文 »
luogu1484 种树 发表于 2018-04-30 12345678910111213大根堆要能够反悔注意到选了一个,它一定比两边的优所以要么选它,要么两边同时选选一个点之后将它两边的值减去它,更新到这个点,删去两边的点这样每轮还是相当于选一个点注意边界处理调了一天要先弹完用过的再判负顺序很重要!顺序很重要!顺序很重要! 阅读全文 »
luogu2278 [HNOI2003]操作系统 发表于 2018-04-28 12345678好久没写重载了less需要重载小于号greater需要重载大于号stl中使用结构体会使成员变量变成private,导致只可访问,不可修改所以成员函数要加constpriority_queue:从小到大排序后每次取最后一个sort/set:从小到大排序 阅读全文 »
luoguP2149 [SDOI2009]Elaxia的路线 发表于 2018-04-28 1234567显然他们只会在一段连续的点上相遇先求出每个点是否在最短路上然后暴力枚举起点和终点这样就a了但过不了bzoj上提供的额外两组数据因为两个点在最短路上不代表它们在同一条最短路上还要判断它们的距离差是否相等 阅读全文 »
luogu1345 [USACO5.4]奶牛的电信Telecowmunication 发表于 2018-04-28 12345678910111213看上去像网络流写了一发80分还以为小细节挂了其实整个程序都是错的。。是求最小的割点数转化成求最小的割边数(最小割)每个点拆成两个点i - 1 - i'原图中的边连INF这样只会割掉1的边相当于割掉了这个点 阅读全文 »
luogu1993 小K的农场 发表于 2018-04-27 1234567891011121314151617一眼差分约束,一眼数据1e4一看题解,全写的是spfa_dfs!?spfa还能用dfs?吓得我赶紧去负环的模板题看题解也是dfs?不过高级的管理员改了数据把复杂度没有保证的dfs全部hack了只能愉快的写bfs啦直接写的话会t新技能:保存每个点的最短路径长度,>n说明出现负环这样写开O2才能a掉但是数据太弱>15就认为出现负环这样就0ms过了顺便做了一下负环的模板题发现记录路径长度比记录进队次数慢。。 阅读全文 »