• SDOI2013 R1 Day1



    2018.3.22 Test

    时间:7:30~11:40
    得分:80+65+20=165

    总结

    时间分配。。
    2个月前写的都忘的差不多了。。
    注意:T2合并一棵子树,这棵子树某些点的dep[x]可能会变小,于是fa[x][..]应变为0,但如果在循环里写 &&(1<<i)<=dep[x] 这个dep[x]是更新后的,fa[x][..]不会被更新成0,还是以前的fa[x][..],于是就挂了。

    T1 BZOJ.3122.[SDOI2013]随机数生成器(BSGS 等比数列)

    题目链接

    想象假装自己学过的必修五数列。。
    (X_i = A*X_{i-1}+B (mod P)),可以化成等差数列(构造一个项使得右边的B能进到括号里,即要减去一个B,且系数要*A,那么左右两边同时 (+frac{B}{A-1}))
    由等差数列第n项公式可得 (X_n + frac{B}{A-1} = A^{n-1}*(X_0 + frac{B}{A-1}) (mod P))
    只有A的次数是不知道的,把右边乘(除)过来就是BSGS了
    要注意这个式子在 A=1 或 A=0 时是无意义的,要特判。

    算出答案后先取模再+1(随便模什么。。)
    我tm可不是sb -> 特判输出2也要模P。。666

    //2788kb	336ms
    #include <cmath>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    #define mod (100005)
    typedef long long LL;
    const int N=1e5+7;
    
    LL P,A,B,X,pur;
    
    struct Hash
    {
    	int H[N],Enum,nxt[N],to[N],res[N],val[N];//数组适当小一些 在清空的情况下更好 
    	void Init(){
    		Enum=0, memset(H,0,sizeof H);
    	}
    	void AddEdge(int id,int v)
    	{
    		int x=v%mod;
    		for(int i=H[x]; i; i=nxt[i])
    			if(val[i]==v) {to[i]=id; return;}
    		to[++Enum]=id, nxt[Enum]=H[x], H[x]=Enum, val[Enum]=v;
    	}
    	int Query(int v)
    	{
    		for(int i=H[v%mod]; i; i=nxt[i])
    			if(val[i]==v) return to[i];
    		return -1;
    	}
    }hs;
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    int gcd(int x,int y){
    	return y?gcd(y,x%y):x;
    }
    void Ex_gcd(int a,int b,LL &x,LL &y){
    	if(!b) x=1ll,y=0ll;
    	else Ex_gcd(b,a%b,y,x),y-=a/b*x;
    }
    LL inv(int v,int p){
    	LL x,y; Ex_gcd(v,p,x,y);
    	return (x%p+p)%p;
    }
    LL FP(LL x,int k)
    {
    	LL t=1;
    	for(; k; k>>=1,x=x*x%P)
    		if(k&1) t=x*t%P;
    	return t;
    }
    int BSGS()//A^x = pur (mod P)
    {
    	pur=(pur+B*inv(A-1,P)%P)*inv(X+B*inv(A-1,P)%P,P)%P;
    	if(gcd(A,P)!=1) return -1;
    	hs.Init();
    	int m=ceil(sqrt(P-1));
    	LL t=pur,AM;
    	for(int i=0; i<=m; ++i,t=t*A%P) hs.AddEdge(i,t);
    	t=AM=FP(A,m);
    	for(int res,i=1; i<=m; ++i,t=t*AM%P)
    		if((res=hs.Query(t))!=-1) return (1ll*i*m-res)%P+1ll;
    	return -1;
    }
    
    int main()
    {
    	int T=read();
    	while(T--)
    	{
    		P=read(),A=read(),B=read(),X=read(),pur=read();
    		if(pur==X) printf("1
    ");
    		else if(!A){//这个只是判B!x_i = 0*x_{i-1}+B = B 
    			printf("%d
    ",B==pur?2:-1);
    		}
    		else if(A==1){//X_1+x*B = pur(mod p) -> x = (pur-X_1)*inv(B) (mod p)
    			if((pur=(pur-X+P)%P)%gcd(B,P)) printf("-1
    ");
    			else printf("%d
    ",(int)(pur*inv(B,P)%P+1ll));
    		}
    		else printf("%d
    ",BSGS());
    	}
    	return 0;
    }
    

    T2 BZOJ.3123.[SDOI2013]森林(主席树 启发式合并)

    题目链接

    查树上第k小可以用主席树,但是合并。。(LCT再维护一个值的Splay行不行。。更改fa,son就Delete,Insert...<-作死的节奏)
    合并两棵树我们可以用启发式合并,logn是可以的。
    合并时还需要动态维护并上去的子树的LCA,所以用ST表求LCA,每次DFS一个点更新ST表即可。
    合并时建主席树和之前DFS建树时是一样的,直接由父节点的root再加上A[x]。但这样每次合并一个点需要新开一个节点。。

    //481804kb	8920ms
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    const int N=8e4+5,B=16;
    
    int n,m,Fa[N],root[N],cnt,ref[N],A[N],dep[N],fa[N][17],sz[N],Enum,H[N],to[N<<1],nxt[N<<1];
    struct Seg_Tree
    {
    	#define lson son[x][0]
    	#define rson son[x][1]
    
    	int tot,sum[N*500],son[N*500][2];//sum[N*18],son[N*18][2];
    	void Insert(int x,int &y,int l,int r,int p)
    	{
    		sum[y=++tot]=sum[x]+1;
    		if(l<r){
    			int m=l+r>>1;
    			if(p<=m) son[y][1]=rson,Insert(lson,son[y][0],l,m,p);
    			else son[y][0]=lson,Insert(rson,son[y][1],m+1,r,p);
    		}
    	}
    	int Query(int x,int y,int lca,int falca,int l,int r,int k)
    	{
    		if(l==r) return l;
    		int delta=sum[lson]+sum[son[y][0]]-sum[son[lca][0]]-sum[son[falca][0]];
    		if(delta>=k) return Query(lson,son[y][0],son[lca][0],son[falca][0],l,l+r>>1,k);
    		return Query(rson,son[y][1],son[lca][1],son[falca][1],(l+r>>1)+1,r,k-delta);
    	}
    }t;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    inline void AddEdge(int u,int v)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    int Find(int x)
    {
    	int l=1,r=cnt,mid;
    	while(l<r)
    		if(ref[mid=l+r>>1]<x) l=mid+1;
    		else r=mid;
    	return l;
    }
    void Discrete()
    {
    	std::sort(ref+1,ref+1+n);
    	cnt=1;
    	for(int i=2; i<=n; ++i)
    		if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
    	for(int i=1; i<=n; ++i) A[i]=Find(A[i]);
    }
    void pre_DFS(int x,int anc)
    {
    	t.Insert(root[fa[x][0]],root[x],1,cnt,A[x]), Fa[x]=anc, ++sz[anc];
    	for(int i=1; i<=B&&(1<<i)<=dep[x]; ++i)
    		fa[x][i]=fa[fa[x][i-1]][i-1];
    	for(int v,i=H[x]; i; i=nxt[i])
    		if((v=to[i])!=fa[x][0])
    			dep[v]=dep[x]+1, fa[v][0]=x, pre_DFS(v,anc);//, sz[x]+=sz[v];
    }
    int LCA(int x,int y)
    {
    	if(dep[x]<dep[y]) std::swap(x,y);
    	int t=dep[x]-dep[y];
    	for(int i=B; i>=0; --i)
    //		if(dep[fa[x][i]]>=dep[x]) x=fa[x][i];
    		if(t&(1<<i)) x=fa[x][i];
    	if(x==y) return x;
    	for(int i=B; i>=0; --i)
    		if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    void DFS(int x)
    {
    	t.Insert(root[fa[x][0]],root[x],1,cnt,A[x]);
    	for(int i=1; i<=B/*&&(1<<i)<=dep[x]*/; ++i)//这个不能写!
    		fa[x][i]=fa[fa[x][i-1]][i-1];
    	for(int v,i=H[x]; i; i=nxt[i])
    		if((v=to[i])!=fa[x][0])
    			dep[v]=dep[x]+1, fa[v][0]=x, DFS(v);
    }
    int Get_fa(int x){
    	return x==Fa[x]?x:Fa[x]=Get_fa(Fa[x]);
    }
    void Union(int x,int y)
    {
    	int r1=Get_fa(x),r2=Get_fa(y);
    	if(sz[r1]>sz[r2]) std::swap(x,y),std::swap(r1,r2);
    	Fa[r1]=r2, sz[r2]+=sz[r1];
    	fa[x][0]=y, dep[x]=dep[y]+1, DFS(x);
    }
    
    int main()
    {
    //	freopen("forest.in","r",stdin);
    //	freopen("forest.out","w",stdout);
    
    //	int size = 256 << 20; // 256MB  
    //	char *p = (char*)malloc(size) + size;  
    //	__asm__("movl %0, %%esp
    " :: "r"(p));
    
    	int test=read(),T;
    	n=read(),m=read(),T=read();
    	for(int i=1; i<=n; ++i) ref[i]=A[i]=read();
    	Discrete();
    	for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),AddEdge(u,v);
    	for(int i=1; i<=n; ++i) if(!dep[i]) pre_DFS(i,i);
    	int ans=0,x,y,w,k; char opt[3];
    	while(T--)
    	{
    		scanf("%s",opt), x=read()^ans, y=read()^ans;
    		if(opt[0]=='Q') k=read()^ans, w=LCA(x,y),printf("%d
    ",ans=ref[t.Query(root[x],root[y],root[w],root[fa[w][0]],1,cnt,k)]);
    		else AddEdge(x,y), Union(x,y);
    	}
    	return 0;
    }
    

    T3 BZOJ.3124.[SDOI2013]直径(树 直径)

    题目链接

    需要判断一条边是否是所有直径都经过的边
    可以证明(想象),树上的多条直径一定是从某个(些)点出发,中间经过同一条链(为方便把链上的边叫做关键边好了),再于某个(些)点结束。
    只需要判断当前求出直径上的所有边是否为关键边。如果一条边(u->v)不是关键边,那么说明它(直径上)的前驱u,除了v之外还有u->v'可以满足最长(得到直径),于是对每个点记录子节点的最远(直径)、次远距离(非严格,在另一棵子树上)就好了。
    如果是从R1出发,这样我们可以判掉R2那边的非关键边,从R2倒着再一遍即可判掉R1,得到中间那条链。

    //17660kb	1932ms
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    const int N=2e5+5;
    const LL INF=1e10;
    
    int n,Ans,root,Enum,H[N],to[N<<1],nxt[N<<1],fa[N];
    LL Max,dis[N],mx[N],s_mx[N],val[N<<1];
    bool is_d[N],Mark[N];
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now*f;
    }
    inline void AddEdge(int u,int v,int w)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, val[Enum]=w;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, val[Enum]=w;
    }
    void pre_DFS(int x,LL d)
    {
    	if(d>Max) Max=d, root=x;
    	for(int i=H[x]; i; i=nxt[i])
    		if(to[i]!=fa[x]) fa[to[i]]=x,pre_DFS(to[i],d+val[i]);
    }
    void DFS(int x,int f)
    {
    	for(int v,i=H[x]; i; i=nxt[i])
    		if((v=to[i])!=f)
    		{
    			DFS(v,x);
    			if(mx[x]<val[i]+mx[v]) mx[x]=val[i]+mx[v];
    			else if(s_mx[x]<val[i]+mx[v]) s_mx[x]=val[i]+mx[v];
    		}
    }
    void DFS_for_Ans(int x,int f,LL d)
    {
    	for(int i=H[x]; i; i=nxt[i])
    			if(to[i]!=f&&is_d[to[i]])
    				if(s_mx[x]+d>=Max) {Mark[x]=1/*在此断开*/; return;}
    	for(int i=H[x]; i; i=nxt[i])
    		if(to[i]!=f&&is_d[to[i]])
    			DFS_for_Ans(to[i],x,d+val[i]);
    }
    
    int main()
    {
    //	freopen("diameter.in","r",stdin);
    //	freopen("diameter.out","w",stdout);
    
    	n=read();
    	for(int u,v,w,i=1; i<n; ++i) u=read(),v=read(),w=read(),AddEdge(u,v,w);
    	Max=-INF, pre_DFS(1,0);
    	int u=root,v;
    	Max=-INF, fa[u]=0, pre_DFS(u,0), v=root;
    	while(root!=u) is_d[root]=1,root=fa[root];
    	is_d[root]=1;
    
    	DFS(u,-1), DFS_for_Ans(u,-1,0);
    	memset(mx,0,sizeof mx), memset(s_mx,0,sizeof s_mx);
    	DFS(v,-1), DFS_for_Ans(v,-1,0);
    	for(bool f=0; v!=u; v=fa[v],Ans+=f)
    		if(Mark[v]) f^=1;
    	printf("%I64d
    %d",Max,Ans);
    
    	return 0;
    }
    

    考试代码

    T1

    #include <cmath>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    #define mod (100005)
    typedef long long LL;
    const int N=1e6+7;
    
    LL P,A,B,X,pur;
    bool vis[500];
    
    struct Hash
    {
    	int H[N],Enum,nxt[N],to[N],res[N],val[N];
    	void Init(){
    		Enum=0, memset(H,0,sizeof H);
    	}
    	void AddEdge(int id,int v)
    	{
    		int x=v%mod;
    		for(int i=H[x]; i; i=nxt[i])
    			if(val[i]==v) {to[i]=id; return;}
    		to[++Enum]=id, nxt[Enum]=H[x], H[x]=Enum, val[Enum]=v;
    	}
    	int Query(int v)
    	{
    		for(int i=H[v%mod]; i; i=nxt[i])
    			if(val[i]==v) return to[i];
    		return -1;
    	}
    }hs;
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    int Spec1()
    {
    	memset(vis,0,sizeof vis);
    	for(int tm=1; !vis[X]; X=(A*X+B)%P,++tm)
    		if(X==pur) return tm;
    		else vis[X]=1;
    	return -1;
    }
    int gcd(int x,int y){
    	return y?gcd(y,x%y):x;
    }
    void Ex_gcd(int a,int b,int &g,LL &x,LL &y){
    	if(!b) x=1ll,y=0ll,g=a;
    	else Ex_gcd(b,a%b,g,y,x),y-=a/b*x;
    }
    int Spec2()
    {
    	if(X==pur) return 1;
    	int R=(pur-X%P+P)%P,gcd; LL x,y;
    	Ex_gcd(B,P,gcd,x,y);
    	if(R%gcd) return -1;
    	x=1ll*x*(R/gcd)%P;
    	P/=gcd;
    	return (x%P+P)%P+1;
    }
    LL inv(int v,int p){
    	LL x,y;int g; Ex_gcd(v,p,g,x,y);
    	return (x%p+p)%p;
    }
    LL FP(LL x,int k)
    {
    	LL t=1;
    	for(; k; k>>=1,x=x*x%P)
    		if(k&1) t=x*t%P;
    	return t;
    }
    int BSGS()
    {
    	if(gcd(A,P)!=1) return -2;
    	hs.Init();
    	int m=ceil(sqrt(P-1));
    	LL t=pur%P,AM;
    	for(int i=0; i<=m; ++i,t=t*A%P) hs.AddEdge(i,t);
    	t=AM=FP(A,m);
    	for(int res,i=1; i<=m; ++i,t=t*AM%P)
    		if((res=hs.Query(t))!=-1) return (1ll*i*m-res)%P;
    	return -2;
    }
    int Spec3()
    {
    	if(X==pur) return 1;
    	pur=pur*inv(X,P)%P;
    	return BSGS()+1;
    }
    
    int main()
    {
    	freopen("random.in","r",stdin);
    	freopen("random.out","w",stdout);
    
    	int T=read();
    	while(T--)
    	{
    		P=read(),A=read(),B=read(),X=read()%P,pur=read();
    		if(P<=100) printf("%d
    ",Spec1());
    		else if(A==1) printf("%d
    ",Spec2());
    		else if(!B) printf("%d
    ",Spec3());
    	}
    	return 0;
    }/*
    1 9 1 6 1 4
    */
    

    T2

    样例LCT哪RE不知道。。没改
    过220行了!写过最长的代码(虽然LCT部分没什么用)

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    const int N=8e4+5;
    
    int n,m;
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now*f;
    }
    #define lson son[x][0]
    #define rson son[x][1]
    namespace LCT
    {
    	int fa[N],son[N][2],val[N],sz[N],sk[N];
    	bool tag[N];
    	inline void Update(int x){
    		sz[x]=sz[lson]+sz[rson]+1;
    	}
    	inline bool n_root(int x){
    		return son[fa[x]][0]==x||son[fa[x]][1]==x;
    	}
    	inline void Rev(int x){
    		std::swap(lson,rson), tag[x]^=1;
    	}
    	inline void PushDown(int x){
    		if(tag[x]) Rev(lson),Rev(rson),tag[x]=0;
    	}
    	void Rotate(int x)
    	{
    		int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
    		if(n_root(a)) son[b][son[b][1]==a]=x;
    		if(son[x][r]) fa[son[x][r]]=a;
    		fa[a]=x, fa[x]=b, son[a][l]=son[x][r], son[x][r]=a;
    		Update(a);
    	}
    	void Splay(int x)
    	{
    		int t=1,a=x,b; sk[1]=x;
    		while(n_root(a)) sk[++t]=a=fa[a];
    		while(t) PushDown(sk[t--]);
    		while(n_root(x))
    		{
    			a=fa[x], b=fa[a];
    			if(n_root(a)) Rotate(son[a][1]==x^son[b][1]==a?x:a);
    			Rotate(x);
    		}
    		Update(x);
    	}
    	void Access(int x){
    		for(int pre=0; x; x=fa[pre=x])
    			Splay(x), rson=pre, Update(x);
    	}
    	void Make_root(int x){
    		Access(x), Splay(x), Rev(x);
    	}
    	void Split(int x,int y){
    		Make_root(x), Access(y), Splay(y);
    	}
    	void Link(int x,int y){
    		Make_root(x), fa[x]=y;
    	}
    }
    namespace Spec
    {
    	int root[N],cnt,A[N],ref[N],Enum,H[N],to[N<<1],nxt[N<<1],top[N],dep[N],sz[N],fa[N],sn[N];
    	bool vis[N];
    	inline void AddEdge(int u,int v)
    	{
    		to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    		to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    	}
    	struct Seg_tree
    	{
    		int tot,sum[N*18],son[N*18][2];
    		void Insert(int x,int &y,int l,int r,int p)
    		{
    			sum[y=++tot]=sum[x]+1;
    			if(l<r)
    			{
    				int m=l+r>>1;
    				if(p<=m) son[y][1]=rson, Insert(lson,son[y][0],l,m,p);
    				else son[y][0]=lson, Insert(rson,son[y][1],m+1,r,p);
    			}
    		}
    		int Query(int x,int y,int z,int w,int l,int r,int k)
    		{
    			if(l==r) return l;
    			int delta=sum[lson]+sum[son[y][0]]-sum[son[z][0]]-sum[son[w][0]];
    			if(delta>=k) return Query(lson,son[y][0],son[z][0],son[w][0],l,l+r>>1,k);
    			return Query(rson,son[y][1],son[z][1],son[w][1],(l+r>>1)+1,r,k-delta);
    		}
    	}t;
    	int Find(int x,int r)
    	{
    		int l=1,mid;
    		while(l<r)
    			if(ref[mid=l+r>>1]>=x) r=mid;
    			else l=mid+1;
    		return l;
    	}
    	void Discrete()
    	{
    		cnt=1;
    		for(int i=2; i<=n; ++i)
    			if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
    		for(int i=1; i<=n; ++i) A[i]=Find(A[i],cnt);
    	}
    	void DFS1(int x)
    	{
    		int mx=0; sz[x]=1;
    		for(int v,i=H[x]; i; i=nxt[i])
    			if((v=to[i])!=fa[x])
    			{
    				dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v];
    				if(sz[v]>mx) mx=sz[v],sn[x]=v;
    			}
    	}
    	void DFS2(int x,int tp)
    	{
    		top[x]=tp;
    		if(sn[x])
    		{
    			DFS2(sn[x],tp);
    			for(int i=H[x]; i; i=nxt[i])
    				if(to[i]!=fa[x]&&to[i]!=sn[x]) DFS2(to[i],to[i]);
    		}
    	}
    	void DFS(int x)
    	{
    		t.Insert(root[fa[x]],root[x],1,cnt,A[x]), vis[x]=1;
    		for(int i=H[x]; i; i=nxt[i])
    			if(to[i]!=fa[x]) fa[to[i]]=x, DFS(to[i]);
    	}
    	int LCA(int u,int v)
    	{
    		while(top[u]!=top[v])
    		{
    			if(dep[top[u]]<dep[top[v]]) std::swap(u,v);
    			u=fa[top[u]];
    		}
    		return dep[u]<dep[v]?u:v;
    	}
    	void Solve(int T)
    	{
    		for(int i=1; i<=n; ++i) ref[i]=A[i]=read();
    		std::sort(ref+1,ref+1+n), Discrete();
    		for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),AddEdge(u,v);
    		for(int i=1; i<=n; ++i) if(!vis[i]) DFS(i);
    		for(int i=1; i<=n; ++i) if(!sz[i]) DFS1(i),DFS2(i,i);
    		int ans=0,x,y,k,w; char opt[3];
    		while(T--)
    		{
    			scanf("%s",opt), x=read()^ans, y=read()^ans,k=read()^ans;
    			w=LCA(x,y), printf("%d
    ",ans=ref[t.Query(root[x],root[y],root[w],root[fa[w]],1,cnt,k)]);
    		}
    	}
    }
    namespace Violence
    {
    	int A[500],Enum,H[500],to[1000],nxt[1000],tmp[1000],pre[1000];
    	bool vis[500];
    	inline void AddEdge(int u,int v)
    	{
    		to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    		to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    	}
    	void DFS(int x,int y,int f)
    	{
    		if(x!=y)
    			for(int i=H[x]; i; i=nxt[i])
    				if(to[i]!=f) pre[to[i]]=x, DFS(to[i],y,x);
    	}
    	int Query(int x,int y,int k)
    	{
    		DFS(x,y,-1);
    		tmp[0]=0;
    		while(y!=x) tmp[++tmp[0]]=A[y],y=pre[y];
    		tmp[++tmp[0]]=A[x];
    		std::sort(tmp+1,tmp+1+tmp[0]);
    		return tmp[k];
    	}
    	void Solve(int T)
    	{
    		for(int i=1; i<=n; ++i) A[i]=read();
    		for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),AddEdge(u,v);
    		int ans=0,x,y,k; char opt[3];
    		while(T--)
    		{
    			scanf("%s",opt), x=read()^ans, y=read()^ans;
    			if(opt[0]=='Q') k=read()^ans, printf("%d
    ",ans=Query(x,y,k));
    			else AddEdge(x,y);
    		}
    	}
    }
    
    int main()
    {
    	freopen("forest.in","r",stdin);
    	freopen("forest.out","w",stdout);
    
    	int test=read(),T;
    	n=read(),m=read(),T=read();
    	if(test==1||test==2) {Violence::Solve(T); return 0;}
    	if((test>=3 && test<=9)||(test>=14 && test<=17)) {Spec::Solve(T);return 0;}
    	for(int i=1; i<=n; ++i) LCT::val[i]=read(),LCT::sz[i]=1;
    	for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),LCT::Link(u,v);
    	int ans=0,x,y,k; char opt[3];
    	while(T--)
    	{
    		scanf("%s",opt), x=read()^ans, y=read()^ans;
    		if(opt[0]=='Q') k=read()^ans, LCT::Split(x,y);
    		else LCT::Link(x,y);
    	}
    	return 0;
    }
    

    T3

    想写树剖没时间了(枚举删边就行啊。。)

    #include <cstdio>
    #include <cctype>
    #define gc() getchar()
    typedef long long LL;
    const int N=2e5+5;
    const LL INF=1e10;
    
    int n,root,Enum,H[N],to[N<<1],nxt[N<<1],val[N<<1];
    LL Max;
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now*f;
    }
    inline void AddEdge(int u,int v,int w)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, val[Enum]=w;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, val[Enum]=w;
    }
    void DFS(int x,int f,LL d)
    {
    	if(d>Max) Max=d, root=x;
    	for(int i=H[x]; i; i=nxt[i])
    		if(to[i]!=f) DFS(to[i],x,d+val[i]);
    }
    namespace Sub
    {
    	#define lson l,m,rt<<1
    	#define rson m+1,r,rt<<1|1
    
    	int dep[N],sz[N],son[N],son_v[N],top[N],cnt,pos[N],fa[N];
    	struct Seg_tree
    	{
    		int sum[N],A[N],tag[N],id[N];
    		inline void PushUp(int rt){
    			sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    		}
    		inline void Add(int x,int v){
    			sum[x]+=v, tag[x]+=v;
    		}
    		void Build(int l,int r,int rt)
    		{
    			if(l==r) sum[rt]=A[l], id[l]=rt;
    			else if(l<r)
    			{
    				int m=l+r>>1;
    				Build(lson), Build(rson);
    				PushUp(rt);
    			}
    		}
    		void Modify(int l,int r,int rt,int L,int R)
    		{
    			if(L<=l&&r<=R) Add(rt,1);
    			else
    			{
    				int m=l+r>>1;
    				if(L<=m) Modify(lson,L,R);
    				if(m<R) Modify(rson,L,R);
    				PushUp(rt);
    			}
    		}
    	}t;
    	void DFS1(int x)
    	{
    		sz[x]=1; int mx=0;
    		for(int v,i=H[x]; i; i=nxt[i])
    			if((v=to[i])!=fa[x])
    			{
    				fa[v]=x, dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v];
    				if(mx<sz[v]) mx=sz[v],son[x]=v,son_v[x]=i;
    			}
    	}
    	void DFS2(int x,int tp)
    	{
    		top[x]=tp;
    		if(son[x])
    		{
    			DFS2(son[x],tp), t.A[pos[son_v[x]]=++cnt]=val[son_v[x]];
    			for(int i=H[x]; i; i=nxt[i])
    				if(to[i]!=fa[x] && to[i]!=son[x])
    					DFS2(to[i],to[i]);
    		}
    	}
    	void Solve()
    	{
    		DFS1(1), DFS2(1,1);
    		for(int i=1; i<=n; ++i) ;
    		
    	}
    }
    
    int main()
    {
    	freopen("diameter.in","r",stdin);
    	freopen("diameter.out","w",stdout);
    
    	n=read();
    	for(int u,v,w,i=1; i<n; ++i) u=read(),v=read(),w=read(),AddEdge(u,v,w);
    	Max=-INF, DFS(1,-1,0);
    	int u=root,v;
    	Max=-INF, DFS(u,-1,0), v=root;
    	printf("%I64d
    ",Max);
    //	Sub::Solve();
    	printf("233");
    
    	return 0;
    }
    
  • 相关阅读:
    Bootstrap 网页1
    Bootstrap 网页实例
    Bootstrap 警告框
    Bootstrap 表格
    Bootstrap 小功能
    【BZOJ1706】[usaco2007 Nov]relays 奶牛接力跑 矩阵乘法
    【BZOJ3669】[Noi2014]魔法森林 LCT
    【BZOJ2049,2631,3282,1180】LCT模板四连A
    【BZOJ4071】[Apio2015]巴邻旁之桥 Treap
    【BZOJ1009】[HNOI2008]GT考试 next数组+矩阵乘法
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8624263.html
走看看 - 开发者的网上家园