题目:维护一个序列,支持将一段数翻转并插到最后的操作,最后输出整个序列。
思路:直接套的大白模板,第一次用splay,贴一下。。


/* *@author: Cwind *http://www.cnblogs.com/Cw-trip/ */ #include <bits/stdc++.h> #define pb push_back #define PB pop_back #define bk back() #define se second #define fs first #define IINF (1<<29) #define sq(x) (x)*(x) #define eps 0.000000001 #define clr(x) memset((x),0,sizeof (x)) using namespace std; typedef long long ll; typedef pair<ll,ll> P; const int maxp=1e6+3000; struct Node{ int s; int val; bool flip; Node *ch[2]; Node():s(0),flip(0){} int cmp(const int k)const { int d=k-ch[0]->s; if(d==1) return -1; else return d>0; } void maintain(){ s=ch[0]->s+ch[1]->s+1; } void pushdown(){ if(flip){ flip=0; swap(ch[0],ch[1]); ch[0]->flip^=1; ch[1]->flip^=1; } } }pool[maxp]; Node *null=new Node(); int ph=0; Node *newNode(){ Node *n=&pool[ph++]; n->flip=n->s=0; return n; } void rotate(Node *&o,int d){ Node *k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->maintain(); k->maintain(); o=k; } void splay(Node *&o,int k){ o->pushdown(); int d=o->cmp(k); if(d==1) k-=o->ch[0]->s+1; if(d!=-1){ Node *p=o->ch[d]; p->pushdown(); int d2=p->cmp(k); int k2=(d2==0?k:k-p->ch[0]->s-1); if(d2!=-1){ splay(p->ch[d2],k2); if(d==d2) rotate(o,d^1);else rotate(o->ch[d],d); } rotate(o,d^1); } } Node* merge(Node *left,Node *right){ splay(left,left->s); left->ch[1]=right; left->maintain(); return left; } void split(Node *o,int k,Node *&left,Node *&right){ splay(o,k); left=o; right=o->ch[1]; o->ch[1]=null; left->maintain(); } int num=0; Node *build(int sz){ if(sz==0) return null; Node *n=newNode(); n->ch[0]=build(sz/2); n->val=num++; n->ch[1]=build(sz-sz/2-1); n->maintain(); return n; } void print(Node *n){ if(n==null) return; n->pushdown(); print(n->ch[0]); if(n->val!=0)printf("%d\n",n->val); print(n->ch[1]); } int n,m; int main(){ freopen("/home/files/CppFiles/in","r",stdin); //freopen("defense.in","r",stdin); //freopen("defense.out","w",stdout); cin>>n>>m; Node *root=build(n+1); while(m--){ int a,b; scanf("%d%d",&a,&b); Node *l,*r,*m,*o; split(root,a,l,o); split(o,b-a+1,m,r); m->flip^=1; root=merge(merge(l,r),m); } print(root); return 0; }
11996
题目:给出一个01序列,要求支持插入,删除,查询任意后缀的lcp。
思路:splay+hash。。。但是看完之后就觉得好难写啊==,遂拖到了昨天,终于下决心填坑。。。。。本来想按着自己的想法写的,结果写完之后连hash值都搞不对。。。。今天果断重写,,继续gg。。。。然后参考例程写了一遍,感觉还是学了几个很重要的技巧的,比如提取一个子串,以及添加一个子串或字符。如果不学习例程的话,我是准备用分裂合并搞的,那样的话效率和写法都很难看。。。。


/* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-3) #define IINF (1<<29) #define LINF (1ll<<59) #define INF 1000000000 typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> P; const int maxp=1e6+3000; const int maxn=2e5+300; int J[maxn]; ull shift[maxn]; ull HV=3137; struct Node *root; int n,m; struct Node{ int s; int val; int id; bool flip; ull h1,h2; Node *ch[2]; Node():s(0),flip(0),h1(0),h2(0){} int cmp(const int k)const { int d=k-ch[0]->s; if(d==1) return -1; else return d>0; } void maintain(){ s=ch[0]->s+ch[1]->s+1; h1=ch[0]->h1+val*shift[ch[0]->s]+ch[1]->h1*shift[ch[0]->s+1]; h2=ch[1]->h2+val*shift[ch[1]->s]+ch[0]->h2*shift[ch[1]->s+1]; } void reverse(){ flip^=1; swap(ch[0],ch[1]); swap(h1,h2); } void pushdown(){ if(flip){ flip=0; ch[0]->reverse(); ch[1]->reverse(); } } }pool[maxp]; Node *null=new Node(); int ph=0; Node *newNode(int val=0){ Node *n=&pool[ph++]; n->flip=0; n->s=1; n->val=n->h1=n->h2=val; n->ch[1]=n->ch[0]=null; return n; } void rotate(Node *&o,int d){ Node *k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->maintain(); k->maintain(); o=k; } void splay(Node *&o,int k){ o->pushdown(); int d=o->cmp(k); if(d==1) k-=o->ch[0]->s+1; if(d!=-1){ Node *p=o->ch[d]; p->pushdown(); int d2=p->cmp(k); int k2=(d2==0?k:k-p->ch[0]->s-1); if(d2!=-1){ splay(p->ch[d2],k2); if(d==d2) rotate(o,d^1);else rotate(o->ch[d],d); } rotate(o,d^1); } } Node *&getRange(int p1,int p2){ splay(root,p1); splay(root->ch[1],p2-p1+1); return root->ch[1]->ch[0]; } Node *getLast(){ return root->ch[1]->ch[0]; } int num=0; int id=0; Node *build(int sz){ if(sz==0) return null; Node *n=newNode(); n->ch[0]=build(sz/2); n->id=id++; n->val=J[num++]; n->ch[1]=build(sz-sz/2-1); n->maintain(); return n; } void update(){ root->ch[1]->maintain(); root->maintain(); } void print(Node *n){ if(n==null) return; n->pushdown(); print(n->ch[0]); printf("%d %d\n",n->val,n->id); print(n->ch[1]); } void init(){ shift[0]=1; for(int i=1;i<maxn;i++){ shift[i]=shift[i-1]*HV; } } char r[maxn]; int main(){ freopen("/home/files/CppFiles/in","r",stdin); //freopen("defense.in","r",stdin); //freopen("defense.out","w",stdout); init(); while(cin>>n>>m){ ph=0,num=0,id=0; scanf("%s",r); for(int i=1;i<=n;i++){ J[i]=r[i-1]-'0'; } J[n+1]=0; root=build(n+2); while(m--){ int Q; scanf("%d",&Q); if(Q==1){ int p,c; scanf("%d%d",&p,&c); p++; getRange(p,p)=newNode(c); update(); }else if(Q==2){ int p; scanf("%d",&p); getRange(p,p+1)=null; update(); }else if(Q==3){ int p1,p2; scanf("%d%d",&p1,&p2); getRange(p1,p2+1)->reverse(); update(); }else{ int p1,p2; scanf("%d%d",&p1,&p2); int l=0,r=root->s-p2; while(r-l>1){ int mid=(r+l)/2; ull h1=getRange(p1,p1+mid)->h1; ull h2=getLast()->h2; h1-=getRange(p2,p2+mid)->h1; h2-=getLast()->h2; if(!h1&&!h2){ l=mid; }else{ r=mid; } } printf("%d\n",l); } } } return 0; }