写了200多行,总是WA,我也实在看不出哪里错了。。
估计问题还在于翻转和查询LCP的地方,可是用10以内的小数据测怎么变都是对的。。
郁闷ing。。
几个细节:
用指针null代替NULL,方便了很多,等于最后叶子节点都指向null,不必每次判断左右子树指针是否为空;
可能我的hash有点问题,我是每次把mid长度的序列从中切下来,得到hash,然后合起来在切开,得到hash2,然后比较,感觉这样比较慢,应该是logn^2的复杂度;
究竟错在哪里,写成这样,很难调啊。。
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
//#define N 400000+5
#define N 200
#define x 89
char str[N];
unsigned long long xp[N];
struct Node {
Node* ch[2];
int v;//value
int size;//sum
int rank;//current tree's position
int flip;//rotate flag
unsigned long long h,cvh;//hash
int cmp(int k) const {
if (k==rank) return -1;
return k<rank? 0 : 1;
}
void pushdown(Node* null){
if (flip) {
flip=0;
swap(ch[0],ch[1]);
if(ch[0]!=null) ch[0]->flip = !ch[0]->flip;
if(ch[1]!=null) ch[1]->flip = !ch[1]->flip;
}
}
void maintain(Node* null){
size=1;
rank=1;
if (ch[0]!=null) {
size+=ch[0]->size;
rank+=ch[0]->size;
}
if (ch[1]!=null) size+=ch[1]->size;
//hash maintain
h = ch[0]->h + v*xp[rank-1] + ch[1]->h*xp[rank];
cvh = ch[1]->cvh + v*xp[size-rank] + ch[0]->cvh*xp[size-rank+1];
}
};
Node* null;
Node* init(int l,int r)
{
Node* p;
int mid=(l+r)>>1;
p=(Node*)malloc(sizeof(Node));
p->size = r-l+1;
p->rank = mid-l+1;
p->v = mid ? str[mid-1]-'0' : 0;
p->flip = 0;
p->ch[0] = p->ch[1] =null;
if (mid-1>=l) p->ch[0]=init(l,mid-1);
if (mid+1<=r) p->ch[1]=init(mid+1,r);
//hash init
p->h = p->ch[0]->h + p->v*xp[p->rank-1] + p->ch[1]->h*xp[p->rank];
p->cvh = p->ch[1]->cvh + p->v*xp[p->size-p->rank] + p->ch[0]->cvh*xp[p->size-p->rank+1];
return p;
}
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(null);
k->maintain(null);
o = k;
}
void splay(Node* &o,int k) {
//correct
o->pushdown(null);
o->maintain(null);
int d= o->cmp(k);
if (d==1) k -= o->rank;
if (d!=-1) {
Node* p = o->ch[d];
//correct
p->pushdown(null);
p->maintain(null);
int d2 = p->cmp(k);
int k2 = (d2==0 ? k : k-p->rank);
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);
}
}
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(null);
}
Node* merge(Node* left,Node* right)
{
splay(left, left->size);
left->ch[1] = right;
left->maintain(null);
return left;
}
void dfs(Node* o) {
o->pushdown(null);
if (o->ch[0]!=null) dfs(o->ch[0]);
printf("%d",o->v);
if (o->ch[1]!=null) dfs(o->ch[1]);
}
int main()
{
freopen("1.in","r",stdin);
xp[0]=1;
for (int i=1;i<=N-5;i++) xp[i]=xp[i-1]*x;
Node* root;
null=(Node*)malloc(sizeof(Node));
null->h = null->cvh = null->flip = null->rank = null->size = null->v = 0;
int L;
int n,m,opt;
while(scanf("%d%d",&n,&m)!=EOF) {
scanf("%s",str);
L=n;
root=init(0,L);
L++;
int p,c,p1,p2;
while (m--) {
scanf("%d",&opt);
Node *left, *mid, *right, *o;
switch(opt){
case 1: scanf("%d%d",&p,&c);
split(root,p+1,left,right);
Node* newp;
newp=(Node*)malloc(sizeof(Node));
newp->size = newp->rank = 1;
newp->flip = 0;
newp->ch[0] = newp->ch[1] = null;
newp->h = newp->cvh = newp->v = c;
root=merge(merge(left,newp),right);
L++;
break;
case 2: scanf("%d",&p);
split(root,p,left,o);
split(o,1,mid,right);
free(mid);
root=merge(left,right);
L--;
break;
case 3: scanf("%d%d",&p1,&p2);
split(root,p1,left,o);
split(o,p2-p1+1,mid,right);
mid->flip ^=1;
//correct
unsigned long long tmp;
tmp = mid->h;
mid->h = mid->cvh;
mid->cvh = tmp;
root = merge(merge(left,mid),right);
break;
default:scanf("%d%d",&p1,&p2);
int P=1, Q=L-p2, MID, ans= 0;
unsigned long long hash, hash2;
while (P<=Q){
MID=(P+Q)>>1;
split(root,p1,left,o);
split(o,MID,mid,right);
//correct flip == 1
//hash=mid->flip ? mid->cvh : mid->h;
hash = mid->h;
root=merge(merge(left,mid),right);
split(root,p2,left,o);
split(o,MID,mid,right);
//correct flip == 1
//hash2=mid->flip ? mid->cvh : mid->h;
hash2 = mid->h;
root=merge(merge(left,mid),right);
if (hash==hash2) {
ans=MID;
P=MID+1;
}
else Q=MID-1;
}
printf("%d\n",ans);
break;
}
//debug
dfs(root);
printf("\n");
}
}
return 0;
}