LCT模板

bzoj2002 弹飞绵羊

调了两小时

注释掉的那一句错了

还在调的可以参考一下

#include<cstdio>
#include<algorithm>
#define rep(a,b,c) for (int a=b;a<=c;a++)
using namespace std;
const int N=200010;
struct dat{
	dat *f,*s[2];
	int sz;
	void up(){
		sz=s[0]->sz+s[1]->sz+1;
	}
}a0[N];
#define isroot(x) (x->f==a0||(x!=x->f->s[0]&&x!=x->f->s[1]))
void rot(dat *x){
	dat *y=x->f,*z=y->f;
	bool dx=x==y->s[1],dy=y==z->s[1];
	x->f=z;
	if (!isroot(y)) z->s[dy]=x;
//	(z->s[dy]=x)->f=z;
	(y->s[dx]=x->s[!dx])->f=y;
	(x->s[!dx]=y)->f=x;
	y->up(),x->up();
}
void splay(dat *x){
	for (;!isroot(x);rot(x)){
		dat *y=x->f,*z=y->f;
		if (isroot(y)) continue;
		bool dx=x==y->s[1],dy=y==z->s[1];
		if (dx==dy) rot(y); else rot(x);
	}
}
void access(dat *x){
	dat *a=a0,*b=x;
	for (;b!=a0;a=b,b=b->f)
		splay(b),b->s[1]=a,b->up();
	splay(x);
}
int n,q,op,x,y;
int main(){
	scanf("%d",&n);
	rep(i,0,n+1) a0[i]=(dat){a0,{a0,a0},i!=0};
	rep(i,1,n){
		int k;
		scanf("%d",&k);
		a0[i].f=a0+min(k+i,n+1);
	}
	scanf("%d",&q);
	while (q--){
		scanf("%d%d",&op,&x),++x;
		if (op==1){
			dat *k=a0+x;
			access(k);
			printf("%d\n",k->s[0]->sz);
		} else {
			int y;
			scanf("%d",&y);
			y+=x;
			if (y>n) y=n+1;
			dat *dx=a0+x,*dy=a0+y;
			access(dx);
			dx->s[0]->f=a0;
			dx->s[0]=a0;
			dx->up();
			access(dy);
			(dy->s[1]=dx)->f=dy;
			dy->up();
		}
	}
	return 0;
}

NOI2014魔法森林

调了四个小时

#include<cstdio>
#include<algorithm>
#define rep(a,b,c) for (int a=b;a<=c;a++)
using namespace std;
const int N=50010,M=100010;
struct edge{int u,v,a,b;}E[M];
bool cmp(edge x,edge y){return x.a<y.a;}
struct dat{
	dat *f,*s[2];
	int k,mx,rev;
	void up(){
		mx=max(k,max(s[0]->mx,s[1]->mx));
	}
	void down(){
		if (!rev) return;
		rev=0;
		s[0]->rev^=1;
		s[1]->rev^=1;
		swap(s[0],s[1]);
	}
}a0[N+M]={{a0,{a0,a0},0,0,0}},*tot=a0;
#define isroot(x) (x->f==a0||(x!=x->f->s[0]&&x!=x->f->s[1]))
void rot(dat *x){
	dat *y=x->f,*z=y->f;
	z->down(),y->down(),x->down();
	bool dx=x==y->s[1],dy=y==z->s[1];
	x->f=z;
	if (!isroot(y)) z->s[dy]=x;
	(y->s[dx]=x->s[!dx])->f=y;
	(x->s[!dx]=y)->f=x;
	y->up(),x->up();
}
void splay(dat *x){
	x->down();
	for (;!isroot(x);rot(x)){
		dat *y=x->f,*z=y->f;
		if (isroot(y)) continue;
		z->down(),y->down(),x->down();
		bool dx=x==y->s[1],dy=y==z->s[1];
		if (dx==dy) rot(y); else rot(x);
	}
}
void access(dat *x){
	x->down();
	dat *a=a0,*b=x;
	for (;b!=a0;a=b,b=b->f)
		splay(b),b->s[1]=a,b->up();
	splay(x);
}
dat *lft(dat *x){
	while (x->down(),x->s[0]!=a0) x=x->s[0];
	splay(x);
	return x;
}
dat *mex(dat *x){
	x->down();
	if (x->mx==x->s[0]->mx) return mex(x->s[0]);
	if (x->mx==x->s[1]->mx) return mex(x->s[1]);
	splay(x);
	return x;
}
dat *newnode(int k){
	*++tot=(dat){a0,a0,a0,k,k,0};
	return tot;
}
#define root(x) (access(x),x->rev^=1)
#define link(x,y) (root(x),x->f=y)
void dfs(dat *x){
	if (x==a0) return;
	x->down();
	dfs(x->s[0]);
	printf("%d-",x-a0);
	dfs(x->s[1]);
}
void print(){
	for (dat *x=a0+1;x<=tot;x++)
		if (isroot(x)) dfs(x->s[0]),
			printf("(%d)-",x-a0),
			dfs(x->s[1]),
			printf("	-->%d\n",x->f-a0);
	puts("--------");
}
void cut(dat *x,dat *y){
//	puts("cut");
	root(y);
//	print();
	access(x);
//	printf("y=%d\n",y-a0);
//	print();
	x->s[0]=y->f=a0;
	x->up();
//	print();
}
int n,m;
void addedge(int u,int v,int k){
	dat *x=a0+u,*y=a0+v,*z;
	root(x);
//	print();
	access(y);
	if (lft(y)!=x){
		z=newnode(k);
		link(x,z);
		link(y,z);
	} else {
//		puts("+eg st");
		splay(y);
//		print();
		z=mex(y);
		if (z->k<=k){
			newnode(233);
			return;
		}
//		cut(z->s[0],z);
//		cut(z->s[1],z);
		cut(a0+E[z-a0-n].u,z);
		cut(a0+E[z-a0-n].v,z);
		z=newnode(k);
		link(x,z);
		link(y,z);
//		print();
//		puts("+eg ed");
	}
}
int getmax(){
	dat *x=a0+1,*y=a0+n;
//	puts("gmx start");
	root(x);
//	print();
	access(y);
//	puts("gmx end");
	if (lft(y)!=x) return 1e6;
	return x->mx;
}
int main(){
	scanf("%d%d",&n,&m);
	rep(i,1,n) newnode(0);
	rep(i,1,m){
		int u,v,c,d;
		scanf("%d%d%d%d",&u,&v,&c,&d);
		E[i]=(edge){u,v,c,d};
	}
	sort(E+1,E+1+m,cmp);
	int ans=1e6;
	rep(i,1,m){
		if (E[i].u==E[i].v){
			newnode(233);
			continue;
		}
		addedge(E[i].u,E[i].v,E[i].b);
//		print();
		ans=min(ans,getmax()+E[i].a);
	}
	printf("%d\n",ans==1e6?-1:ans);
//	getchar(),getchar();
	return 0;
}

还有个造数据

#include<cstdio>
#include<algorithm>
#define rep(a,b,c) for (int a=b;a<=c;a++)
using namespace std;
int main(){
	srand(time(0));
	int n=20,m=600;
	printf("%d %d\n",n,m);
	rep(i,1,m){
		int u=rand()%n+1,v=rand()%n+1,k1=rand()%m+1,k2=rand()%m+1;
		printf("%d %d %d %d\n",u,v,k1,k2);
	}
	return 0;
}

如果帮你省了时间就坠吼了T_T


还有道wwt大爷出的题(应该是的)

想做最好先会palindromic tree2333

图转侵删



#include<cstdio>
#include<cstring>
#define rep(a,b,c) for (int a=b;a<=c;a++)
using namespace std;
typedef long long LL;
const int N=100010;
int Str[N<<1],*str=Str+N;
LL ans;
struct dat{
	dat *f,*s[2];
	LL k,ks,sum,sk,tag;
	void operator +=(int x){
		tag+=x;
		sum+=sk*x;
		ks+=k*x;
	}
	void up(){
		sk=k+s[0]->sk+s[1]->sk;
		sum=ks+s[0]->sum+s[1]->sum;
	}
	void down(){
		(*s[0])+=tag;
		(*s[1])+=tag;
		tag=0;
	}
}a0[N]={{a0,{a0,a0}}};
void newnode(int x,int k,int f){
	a0[x]=(dat){a0+f,a0,a0,k,0,0,k,0};
}
#define isroot(x) (x->f==a0||(x->f->s[0]!=x&&x->f->s[1]!=x))
void rot(dat *x){
	dat *y=x->f,*z=y->f;
	bool dx=x==y->s[1],dy=y==z->s[1];
	x->f=z;
	if (!isroot(y)) z->s[dy]=x;
	(y->s[dx]=x->s[!dx])->f=y;
	(x->s[!dx]=y)->f=x;
	y->up(),x->up();
}
void splay(dat *x){
	static dat *q[N];
	int t=0;
	do q[++t]=x,x=x->f; while (!isroot(q[t]));
	while (t) q[t--]->down();
	for (x=q[1];!isroot(x);rot(x)){
		dat *y=x->f,*z=y->f;
		if (isroot(y)) continue;
		bool dx=x==y->s[1],dy=y==z->s[1];
		if (dx==dy) rot(y); else rot(x);
	}
}
void access(dat *x){
	dat *a=a0,*b=x;
	for (;b->f!=a0;a=b,b=b->f)
		splay(b),b->s[1]=a,b->up();
	splay(x);
}
void add(int x){
	dat *t=a0+x;
//	while (t){
//		t->s+=t->k;
//		t=t->f;
//	}
	access(t);
	*t+=1;
}
LL ask(int x){
	LL ans=0;
	dat *t=a0+x;
//	while (t){
//		ans+=t->s;
//		t=t->f;
//	}
	access(a0+x);
	return (a0+x)->sum;
}
struct p_tree{
	int len,cur,tot,l[N],f[N],s[N][26];
	void init(){
		len=0;
		cur=tot=2;
		f[2]=f[1]=1;
		l[1]=-1;
		l[2]=0;
		newnode(1,0,0);
		newnode(2,0,1);
	}
	void extend(int c){
		while (str[len-cur[l]]!=c) cur=cur[f];
		if (!cur[s][c]){
			cur[s][c]=++tot;
			tot[l]=cur[l]+2;
			if (tot[l]==1) tot[f]=2; else {
				int k=cur[f];
				while (str[len-k[l]]!=c) k=k[f];
				tot[f]=k[s][c];
			}
			newnode(tot,tot[l]-tot[f][l],tot[f]);
		}
		cur=cur[s][c];
		add(cur);
		++len;
	}
}pt;
int n,tp;
int main(){
	memset(Str,-1,sizeof(Str));
	pt.init();
	scanf("%d%d",&n,&tp);
	LL lst=0;
	rep(i,1,n){
		scanf("%d",str+i);
		str[i]^=tp*lst;
		pt.extend(str[i]);
		printf("%lld\n",lst=(ans+=ask(pt.cur)));
	}
	return 0;
}

还有bzoj2555,等下写

写完放SAM模板了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值