zoukankan      html  css  js  c++  java
  • 2019.10.25~今近况

    感觉最近好久没有写博客了。

    今天晚上停下来整理一下?回忆一下这几天都干了什么?

    最后还是停课了的说

    上一篇博客是[SCOI2010]序列操作,也已经怪久远的了。

    做完序列操作以后,又去做了一个简化版(?)的线段树板子型的题(?)

    p2253好一个一中腰鼓

    做完了序列操作,这道题真的算是简单到炸了;

    不想写思路了(懒得回忆),就直接放代码吧:

    CODE:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read() {
    	int ans=0;
    	char last=' ',ch=getchar();
    	while(ch>'9'||ch<'0') last=ch,ch=getchar();
    	while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	if(last=='-') ans=-ans;
    	return ans;
    }
    const int mxn=20010;
    
    int n,m,maxn;
    struct node {
    	int l,r;
    	int R,L;
    	int mx;
    	//0 red 1 white
    }t[mxn<<2];
    
    void pushup(int k,int l,int r) {
    	t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
    	if(t[k<<1].r!=t[k<<1|1].l)
    		t[k].mx=max(t[k].mx,t[k<<1].R+t[k<<1|1].L);
    	
    	t[k].l=t[k<<1].l;
    	t[k].r=t[k<<1|1].r;
    	
    	int mid=(l+r)>>1;
    	t[k].L=t[k<<1].L;
    	if(t[k<<1].L==mid-l+1&&t[k<<1].r!=t[k<<1|1].l) 
    		t[k].L+=t[k<<1|1].L;
    	t[k].R=t[k<<1|1].R;
    	if(t[k<<1|1].R==r-mid&&t[k<<1].r!=t[k<<1|1].l)
    		t[k].R+=t[k<<1].R;
    }
    
    void build(int k,int l,int r) {
    	maxn=max(maxn,k);
    	if(l==r) {
    		t[k].l=t[k].r=0;
    		t[k].L=t[k].R=1;
    		t[k].mx=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    	pushup(k,l,r);
    }
    
    void change(int k,int l,int r,int x) {
    	if(l==r) {
    		t[k].l^=1;
    		t[k].r^=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid) change(k<<1,l,mid,x);
    	if(x>mid) change(k<<1|1,mid+1,r,x);
    	pushup(k,l,r);
    }
    
    int main() {
    	n=read();
    	m=read();
    	build(1,1,n);
    	for(int i=1,x;i<=m;i++) {
    		x=read();
    		change(1,1,n,x);
    		printf("%d
    ",t[1].mx);
    	}
    	return 0;
    }
    
    

    然后ych讲了2-sat和建边优化(只学会了2-sat的说)

    因为ych讲的时候提了一句差分约束,咱就先去做了差分约束的题:

    P1993 小K的农场

    大概是用到了dfs-spfa判负环,还引发了zay关于dfs-spfa与bfs-spfa的讨论

    题目思路很简单就是差分约束的标准建边思路,因为只需要判断行不行而不需要输出方案,因此我们可以用dfs-spfa来判断负环(快?)

    CODE:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read() {
    	int ans=0;
    	char last=' ',ch=getchar();
    	while(ch>'9'||ch<'0') last=ch,ch=getchar();
    	while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	if(last=='-') ans=-ans;
    	return ans;
    }
    
    int n,m;
    const int mxn=100100;
    const int inf=2147483647;
    
    int ecnt,head[mxn];
    struct E {
    	int to,dis,nxt;
    } e[mxn<<1];
    
    void add(int from,int to,int dis) {
    	++ecnt;
    	e[ecnt].to=to;
    	e[ecnt].dis=dis;
    	e[ecnt].nxt=head[from];
    	head[from]=ecnt;
    }
    
    queue<int> q;
    int dis[mxn],cnt[mxn];
    bool vis[mxn],bj;
    
    bool spfa(int u) {
    	vis[u]=1;
    	for(int i=head[u],v; i; i=e[i].nxt) {
    		v=e[i].to;
    		if(dis[v]>dis[u]+e[i].dis) {
    			dis[v]=dis[u]+e[i].dis;
    			if(!vis[v]) {
    				if(!spfa(v))
    					return 0;
    			} else
    				return 0;
    		}
    	}
    	vis[u]=0;
    	return 1;
    }
    
    int main() {
    	n=read();
    	m=read();
    	for(int i=1; i<=n; i++)
    		add(0,i,0),dis[i]=inf;
    	for(int i=1,op; i<=m; i++) {
    		op=read();
    		int a,b,c;
    		a=read();
    		b=read();
    		if(op==1) {
    			c=read();
    			add(a,b,-c);
    		}
    		if(op==2) {
    			c=read();
    			add(b,a,c);
    		}
    		if(op==3) {
    			add(a,b,0);
    			add(b,a,0);
    		}
    	}
    	dis[0]=0;
    	if(spfa(0))
    		printf("Yes
    ");
    	else
    		printf("No
    ");
    	return 0;
    }
    

    然后就去做了判负环的模板:

    P3385【模板】负环

    很迷的是用dfs-spfa T了(不是很惨烈.jpg),然后bfs-spfa自己手残写炸了,然后又T又WA了好久/wx

    最后终于手写bfs-spfa过的

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read() {
    	int ans=0;
    	char last=' ',ch=getchar();
    	while(ch>'9'||ch<'0') last=ch,ch=getchar();
    	while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	if(last=='-') ans=-ans;
    	return ans;
    }
    
    int T,n,m;
    const int mxn=3000;
    const int inf=2147483647;
    
    int ecnt,head[mxn];
    struct E {
    	int to,dis,nxt;
    } e[mxn<<1];
    
    void add(int from,int to,int dis) {
    	++ecnt;
    	e[ecnt].to=to;
    	e[ecnt].dis=dis;
    	e[ecnt].nxt=head[from];
    	head[from]=ecnt;
    }
    bool fh,vis[mxn];
    int dis[mxn];
    /*void spfa(int u) {
    	vis[u]=1;
    	for(int i=head[u],v;i;i=e[i].nxt) {
    		v=e[i].to;
    		if(dis[v]>dis[u]+e[i].dis) {
    			dis[v]=dis[u]+e[i].dis;
    			if(vis[v]) {
    				fh=1;
    				return;
    			}
    			spfa(v);
    		}
    	}
    	vis[u]=0;
    }*/
    int cnt[mxn];
    queue<int> q;
    void spfa(int s) {
    	while(!q.empty()) 
    		q.pop();
    	dis[s]=0;
    	vis[s]=1;
    	q.push(s);
    	cnt[s]=1;
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		
    		if(cnt[u]==n) {
    			fh=1;
    			break;
    		}
    		cnt[u]++;
    		vis[u]=0;
    		for(int i=head[u],v;i;i=e[i].nxt) {
    			v=e[i].to;
    			if(dis[v]>dis[u]+e[i].dis) {
    				dis[v]=dis[u]+e[i].dis;
    				if(!vis[v]) {
    					q.push(v);
    					vis[v]=1;
    				}
    			}
    		}
    	}
    }
    
    void clear() {
    	ecnt=0;
    	fh=0;
    	for(int i=1;i<=n+5;i++) {
    		dis[i]=0x3f3f3f3f;
    		vis[i]=0;
    		head[i]=0;
    		cnt[i]=0;
    	}
    }
    
    int main() {
    	T=read();
    	while(T--) {
    		n=read();
    		m=read();
    		clear();
    		for(int i=1,a,b,w;i<=m;i++) {
    			a=read();
    			b=read();
    			w=read();
    			if(w<0) 
    				add(a,b,w);
    			else {
    				add(a,b,w);
    				add(b,a,w);
    			}
    		}
    		spfa(1);
    		if(fh) 
    			printf("YE5
    ");
    		else 
    			printf("N0
    ");
    	}
    	return 0;
    }
    

    然后差分约束还是没做完,又去做了还算简单的

    [USACO05DEC]布局

    这个题中,我莫名的和所有题解的建边都不一样。

    但是要注意到的是一定要在相邻两个点之间连一条权值为0的边,来规范后一头奶牛的位置一定要>=前一头奶牛的位置。并且因为图可能会不连通,所以这个时候我们为了判断是否有合法的解(先不管解是+∞还是有穷),还要建一个超级原点‘0’,从‘0’跑一次spfa(最短路),来判断是否有负环;

    判断完负环之后,为了确定解是+∞还是有穷的,我们需要从n点(为什么从n开始跑我也不知道因为不从n开始跑答案不对,举例子试出来的),再跑一遍spfa(最短路),若1点的dis值为我们初始化的正无穷,那么说明答案是+∞,也就可以输出-2,否则输出dis[1];

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read() {
    	int ans=0;
    	char last=' ',ch=getchar();
    	while(ch>'9'||ch<'0') last=ch,ch=getchar();
    	while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	if(last=='-') ans=-ans;
    	return ans;
    }
    const int mxn=100000;
    
    int n,ml,md;
    struct E{
    	int to,dis,nxt;
    }e[mxn<<1];
    int ecnt,head[mxn];
    void add(int from,int to,int dis) {
    	++ecnt;
    	e[ecnt].dis=dis;
    	e[ecnt].to=to;
    	e[ecnt].nxt=head[from];
    	head[from]=ecnt;
    }
    queue<int> q;
    int dis[mxn],cnt[mxn];
    bool vis[mxn],wj;
    void spfa(int s) {
    	for(int i=1;i<=n;i++) dis[i]=2147483647,vis[i]=0;
    	q.push(s);
    	dis[s]=0;
    	vis[s]=1;
    	while(!q.empty()) {
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		if(cnt[u]==n-1) {
    			wj=1;
    			return;
    		}
    		cnt[u]++;
    		for(int i=head[u],v;i;i=e[i].nxt) {
    			v=e[i].to;
    			if(dis[v]>dis[u]+e[i].dis) {
    				dis[v]=dis[u]+e[i].dis;
    				if(!vis[v]) {
    					q.push(v);
    					vis[v]=1;
    				}
    			}
    		}
    	}
    }
    
    int main() {
    	n=read();
    	ml=read();
    	md=read();
    	int a,b,d;
    	for(int i=1;i<=ml;i++) {
    		a=read();
    		b=read();
    		d=read();
    //		add(a,b,-d);
    		add(b,a,d);//a-b<=d
    	}
    	for(int i=1;i<=md;i++) {
    		a=read();
    		b=read();
    		d=read();
    //		add(b,a,d);
    		add(a,b,-d);//a-b>=d
    	}
    	for(int i=1;i<=n;i++) {
    		add(0,i,0);
    		if(i==1) continue;
    		add(i-1,i,0);
    	}
    	spfa(0);
    	if(wj==1) {
    		printf("-1");
    	} else {
    		spfa(n);
    		if(dis[1]==2147483647) 
    			printf("-2");
    		else 
    			printf("%d
    ",dis[1]);
    	}
    	return 0;
    }
    

    (color{#14c4ff}{接下来终于到了2-sat!!!})

    第一遍还又WA又R,惨得很嘞。

    对于方案输出是一懵一懵的lz

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    
    using namespace std;
    
    inline int read() {
    	int ans=0;
    	char last=' ',ch=getchar();
    	while(ch>'9'||ch<'0') last=ch,ch=getchar();
    	while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	if(last=='-') ans=-ans;
    	return ans;
    }
    const int mxn=2000010;
    
    int n,m;
    
    struct node {
    	int to,nxt;
    }e[mxn<<3];
    int ecnt,head[mxn];
    void add(int from,int to) {
    	++ecnt;
    	e[ecnt].to=to;
    	e[ecnt].nxt=head[from];
    	head[from]=ecnt;
    }
    int dfn[mxn],low[mxn],cnt;
    bool vis[mxn];
    int s[mxn],top;
    int scc[mxn],scc_cnt;
    
    void tarjan(int u){
    	dfn[u]=low[u]=++cnt;
    	vis[u]=1;
    	s[top++]=u;
    	for(int i=head[u],v;i;i=e[i].nxt) {
    		v=e[i].to;
    		if(!dfn[v]) {
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		} else 
    			if(vis[v])
    				low[u]=min(low[u],dfn[v]);
    	}
    	if(low[u]==dfn[u]) {
    		scc_cnt++;
    		while(s[top]!=u) {
    			top--;
    			scc[s[top]]=scc_cnt;
    			vis[s[top]]=0;
    		}
    	}
    }
    
    int main() {
    //	freopen("testdata.in","r",stdin);
    	n=read();
    	m=read();
    	int i,a,j,b;
    	for(int l=1;l<=m;l++) {
    		i=read();
    		a=read();
    		j=read();
    		b=read();
    		if(a==1&&b==1) add(j+n,i),add(i+n,j);
    		if(a==1&&b==0) add(i+n,j+n),add(j,i);
    		if(a==0&&b==1) add(i,j),add(j+n,i+n);
    		if(a==0&&b==0) add(i,j+n),add(j,i+n);
    	}
    	for(int i=1;i<=2*n;i++)
    		if(!dfn[i]) 
    			tarjan(i);
    	for(int i=1;i<=n;i++) 
    		if(scc[i]==scc[i+n]) {
    			printf("IMPOSSIBLE");
    			return 0;
    		}
    	printf("POSSIBLE
    ");
    	for(int i=1;i<=n;i++) 
    		printf("%d ",scc[i]<scc[i+n]);
    	return 0;
    }
    

    然后做了道带权并查集

    P1196[NOI2002]银河英雄传说

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read() {
    	int ans=0;
    	char last=' ',ch=getchar();
    	while(ch>'9'||ch<'0') last=ch,ch=getchar();
    	while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	if(last=='-') ans=-ans;
    	return ans;
    }
    
    inline char Getchar() {
    	char a;
    	do {
    		a=getchar();
    	}while(a!='M'&&a!='C');
    	return a;
    }
    
    struct node {
    	int head,dist,cnt;
    }boat[30010];
    
    int T;
    int fa[30010];
    
    int find(int x) {
    	if(fa[x]==x) return x;
    	int k=fa[x];
    	fa[x]=find(fa[x]);
    	boat[x].dist+=boat[k].dist;
    	boat[x].cnt=boat[k].cnt;
    	return fa[x];
    }
    
    void Union(int A,int B) {
    	int x=find(A),y=find(B);
    	fa[x]=y;
    	boat[x].dist+=boat[y].cnt;
    	boat[y].cnt+=boat[x].cnt;
    	boat[x].cnt=boat[y].cnt;
    }
    
    int main() {
    	T=read();
    	char c;
    	int a,b;
    	for(int i=1;i<=30000;i++) {
    		boat[i].head=i;
    		boat[i].dist=0;
    		boat[i].cnt=1;
    		fa[i]=i;
    	}
    	while(T--) {
    		c=Getchar();
    		a=read();
    		b=read();
    		if(c=='M') {
    			Union(a,b);
    		//	printf("%d %d %d %d %d %d
    ",boat[a].cnt,boat[a].dist,boat[a].head,boat[b].cnt,
    		//		boat[b].dist,boat[b].head);
    		}
    		else {
    			int x=find(a);
    			int y=find(b); 
    			if(x!=y)
    				printf("-1
    ");
    			else 
    				printf("%d
    ",abs(boat[a].dist-boat[b].dist)-1);
    		}
    	}
    	return 0;
    }
    

    然后!过了模拟Mayan游戏(但跑的是真慢,总感觉是卡过去的w)

    本来是有400多行的.jpg,后来发现自己写挂掉了,删了三百多航重构的

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read() {
    	int ans=0;
    	char last=' ',ch=getchar();
    	while(ch>'9'||ch<'0') last=ch,ch=getchar();
    	while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	if(last=='-') ans=-ans;
    	return ans;
    }
    void down(int x,int y,int cnt);
    
    int n;
    int Mp[6][6][8];
    int color[6][12];
    
    void copy(int step) {
    	for(int i=0;i<5;i++) 
    		for(int j=0;j<7;j++) 
    			Mp[step][i][j]=Mp[step-1][i][j];
    }
    
    bool check(int step) {
    	int ans=0;
    	for(int i=0;i<5;i++) 
    		ans+=Mp[step][i][0];
    	return ans==0?1:0;
    }
    
    void Down(int x,int cnt) {//down mei yi shu lie? 
    	int i;
    	bool bj=0;
    	for(i=0;i<7;i++) { 
    		if(Mp[cnt][x][i]==0) 
    			bj=1;
    		if(Mp[cnt][x][i]!=0&&bj==1) { 
    			down(x,i,cnt);
    			bj=0;
    		}
    	}
    }
    
    void down(int x,int y,int cnt) {// xia luo (x,y) xu yao you yan se 
    	int CNT=0;
    	for(int i=y;i<7;i++) 
    		if(Mp[cnt][x][i]!=0) CNT++;
    	for(int i=y-1;i>=0;i--) {
    		if(Mp[cnt][x][i]==0) {
    			for(int j=0;j<CNT;j++) 
    				Mp[cnt][x][j+i]=Mp[cnt][x][i+j+1];
    			Mp[cnt][x][i+CNT]=0;
    		}
    	}
    }
    
    int heng[8][2],shu[6][2][2];
    void xiaochu(int cnt) {
    	memset(shu,0,sizeof(shu));
    	memset(heng,0,sizeof(heng));
    	for(int y=0;y<7;y++) {
    		int CNT=1;
    		for(int i=0;i<4;i++) {
    			if(Mp[cnt][i][y]==Mp[cnt][i+1][y]) CNT++;
    			else {
    				if(CNT>=3) {heng[y][1]=i;heng[y][0]=i-CNT+1;CNT=1;}
    				else CNT=1;
    			}
    		}
    		if(CNT>=3) {heng[y][1]=4;heng[y][0]=4-CNT+1;}
    	}
    	for(int x=0;x<5;x++) {
    		int CNT=1;
    		for(int i=0;i<6;i++) {
    			if(Mp[cnt][x][i]==Mp[cnt][x][i+1]) 
    				CNT++;
    			else {
    				if(CNT>=3) {
    					if(shu[x][0][1]!=0) {shu[x][1][1]=i;shu[x][1][0]=i-CNT+1;} 
    					else {shu[x][0][1]=i;shu[x][0][0]=i-CNT+1;}
    					CNT=1;
    				} else CNT=1;
    			}
    		}
    		if(CNT>=3) {
    			if(shu[x][0][1]!=0) {shu[x][1][1]=6;shu[x][1][0]=6-CNT+1;} 
    			else {shu[x][0][1]=6;shu[x][0][0]=6-CNT+1;}
    		}
    	}
    	for(int i=0;i<5;i++) {
    		if(shu[i][0][0]==shu[i][0][1]) continue;
    		for(int j=shu[i][0][0];j<=shu[i][0][1];j++)
    			Mp[cnt][i][j]=0;
    	}
    	for(int i=0;i<5;i++) {
    		if(shu[i][1][0]==shu[i][1][1]) continue;
    		for(int j=shu[i][1][0];j<=shu[i][1][1];j++) 
    			Mp[cnt][i][j]=0;
    	}
    	for(int i=0;i<7;i++) {
    		if(heng[i][0]==heng[i][1]) continue;
    		for(int j=heng[i][0];j<=heng[i][1];j++) 
    			Mp[cnt][j][i]=0;
    	}
    	for(int i=0;i<5;i++) 
    		Down(i,cnt);
    }
    
    void moved(int x,int y,int l,int cnt) {
    	if(l==1) {
    		swap(Mp[cnt][x][y],Mp[cnt][x+1][y]);
    		Down(x,cnt);
    		Down(x+1,cnt);
    	} else {
    		swap(Mp[cnt][x][y],Mp[cnt][x-1][y]);
    		Down(x,cnt);
    		Down(x-1,cnt);
    	}
    	int J=5;
    	while(J--) xiaochu(cnt);
    }
    
    struct node {
    	int x,y,l;
    }sp[6];
    bool Bj,change[6][8][2];
    bool panduan(int i,int j,int l,int cnt) {
    	if(i!=4&&l==0&&Mp[cnt-1][i-1][j]!=0) return 0;
    	if(i==0&&l==0) return 0;
    	if(i==4&&l==1) return 0;
    	if(change[i][j][l]==1) return 0;
    	if(l==0&&Mp[cnt-1][i][j]==Mp[cnt-1][i-1][j]) return 0;
    	if(l==1&&Mp[cnt-1][i][j]==Mp[cnt-1][i+1][j]) return 0;
    	return 1;
    }
    
    void dfs(int cnt) {
    	if(Bj==1) return ;
    	if(cnt==n+1) {
    		xiaochu(n);
    		if(check(n)) {
    			for(int i=1;i<=n;i++)
    				printf("%d %d %d
    ",sp[i].x,sp[i].y,sp[i].l);
    			Bj=1;
    		}
    		return;
    	}
    	if(cnt>n) return;
    	
    	for(int i=0;i<5;i++) {
    		for(int j=0;j<7;j++) {
    			if(Mp[cnt-1][i][j]==0) break;
    			for(int l=1;l>=0;l--) { 
    				copy(cnt);
    				if(!panduan(i,j,l,cnt)) continue;
    				sp[cnt].x=i;
    				sp[cnt].y=j;
    				sp[cnt].l=(l==0?-1:1);
    				if(l==1) change[i+1][j][0]=change[i][j][l]=1;
    				else change[i-1][j][1]=change[i][j][l]=1;
    				moved(i,j,l,cnt);
    				dfs(cnt+1);
    				if(l==1) change[i+1][j][0]=change[i][j][l]=0;
    				else change[i-1][j][1]=change[i][j][l]=0;
    			}
    		}
    	}
    }
    
    int main() {
    	n=read();
    	for(int i=0,a;i<5;i++) {
    		int j=0;
    		do {
    			a=read();
    			Mp[0][i][j++]=a;
    		}while(a!=0) ;
    	}
    	dfs(1);
    	if(Bj==0) puts("-1");
    	return 0;
    }
    

    还有很早之前的染色:

    (是越发敷衍的lz)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read() {
    	int ans=0;
    	char last=' ',ch=getchar();
    	while(ch>'9'||ch<'0') last=ch,ch=getchar();
    	while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    	if(last=='-') ans=-ans;
    	return ans;
    }
    const int mxn=1500010;
    int n,m;
    struct E {
    	int to,nxt;
    }e[mxn<<1];
    int head[mxn],ecnt;
    void add(int from,int to) {
    	++ecnt;
    	e[ecnt].to=to;
    	e[ecnt].nxt=head[from];
    	head[from]=ecnt;
    }
    
    char Getchar() {
    	char c;
    	do {
    		c=getchar();
    	}while(c!='C'&&c!='Q');
    	return c;
    }
    int siz[mxn],son[mxn],dep[mxn],fa[mxn];
    void dfs1(int u,int f) {
    	dep[u]=dep[f]+1;
    	fa[u]=f;
    	siz[u]=1;
    	int maxn=-1;
    	for(int i=head[u],v;i;i=e[i].nxt) {
    		v=e[i].to;
    		if(v==f) continue;
    		dfs1(v,u);
    		siz[u]+=siz[v];
    		if(siz[v]>maxn) {
    			maxn=siz[v];
    			son[u]=v;
    		}
    	}
    }
    int id;
    int top[mxn],dfn[mxn],num[mxn];
    void dfs2(int u,int f) {
    	dfn[u]=++id;
    	num[id]=u;
    	if(son[f]==u) top[u]=top[f];
    	else top[u]=u;
    	if(son[u]) dfs2(son[u],u);
    	for(int i=head[u],v;i;i=e[i].nxt) {
    		v=e[i].to;
    		if(v==son[u]||v==f) continue;
    		dfs2(v,u);
    	}
    }
    
    struct node {
    	int l,r,cnt;
    }t[mxn<<2];
    
    void update(int k,int l,int r) {
    	t[k].l=t[k<<1].l;
    	t[k].r=t[k<<1|1].r;
    	t[k].cnt=t[k<<1].cnt+t[k<<1|1].cnt;
    	if(t[k<<1].r==t[k<<1|1].l) t[k].cnt--;
    }
    
    int color[mxn];
    
    void build(int k,int l,int r) {
    	if(l==r) {
    		t[k].l=t[k].r=color[num[l]];
    		t[k].cnt=1;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    	update(k,l,r);
    }
    int tag[mxn];
    
    void pushdown(int k,int l,int r) {
    	if(tag[k]==0) return ;
    	t[k<<1].cnt=t[k<<1|1].cnt=1;
    	t[k<<1].l=t[k<<1].r=t[k<<1|1].l=t[k<<1|1].r=tag[k];
    	tag[k<<1]=tag[k<<1|1]=tag[k];
    	tag[k]=0;
    }
    
    void modify(int k,int l,int r,int x,int y,int c) {
    	if(x<=l&&r<=y) {
    		t[k].cnt=1;
    		t[k].l=t[k].r=c;
    		tag[k]=c;
    		return ;
    	}
    	pushdown(k,l,r);
    	int mid=(l+r)>>1;
    	if(x<=mid) modify(k<<1,l,mid,x,y,c);
    	if(y>mid) modify(k<<1|1,mid+1,r,x,y,c);
    	update(k,l,r);
    }
    
    void lca(int x,int y,int c) {
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]>dep[top[y]]) {
    			modify(1,1,n,dfn[top[x]],dfn[x],c);
    			x=fa[top[x]];
    		} else {
    			modify(1,1,n,dfn[top[y]],dfn[y],c);
    			y=fa[top[y]];
    		}
    	}
    	if(dep[x]>dep[y]) 
    		swap(x,y);
    	modify(1,1,n,dfn[x],dfn[y],c);
    }
    int ltr,rtr;
    int query(int k,int l,int r,int x,int y) {
    	if(x<=l&&r<=y) {
    		if(x==l) ltr=t[k].l;
    		if(r==y) rtr=t[k].r;
    		return t[k].cnt;
    	}
    	int cnt=0;
    	int mid=(l+r)>>1;
    	pushdown(k,l,r);
    	if(x<=mid) cnt+=query(k<<1,l,mid,x,y);
    	if(y>mid) cnt+=query(k<<1|1,mid+1,r,x,y); 
    	if(x<=mid&&y>mid) {
    		if(t[k<<1].r==t[k<<1|1].l)
    			cnt--;
    	}
    	return cnt;
    }
    
    int getans(int x,int y) {
    	int cnt=0;
    	int topx=0,topy=0,ftopx=-1,ftopy=-1;
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]>dep[top[y]]) {
    			cnt+=query(1,1,n,dfn[top[x]],dfn[x]);
    			if(topx!=0) 
    				if(topx==rtr) 
    					cnt--;
    			topx=ltr;
    			x=fa[top[x]];
    		}else {
    			cnt+=query(1,1,n,dfn[top[y]],dfn[y]);
    			if(topy!=0) 
    				if(topy==rtr)
    					cnt--;
    			topy=ltr;
    			y=fa[top[y]];
    		}
    	}
    	if(dep[x]>dep[y]) {swap(x,y);swap(topx,topy);}
    	cnt+=query(1,1,n,dfn[x],dfn[y]);
    	if(topx==ltr) cnt--;
    	if(topy==rtr) cnt--;
    	return cnt;
    }
    
    int main() {
    	n=read();
    	m=read();
    	for(int i=1;i<=n;i++) color[i]=read();
    	for(int i=1,x,y;i<n;i++) {
    		x=read();
    		y=read();
    		add(x,y);
    		add(y,x);
    	}
    	dfs1(1,0);
    	dfs2(1,0);
    	build(1,1,n);
    	char c;
    	for(int i=1,a,b,c;i<=m;i++) {
    		c=Getchar();
    		if(c=='Q') {
    			a=read();
    			b=read();
    			int k=getans(a,b);
    			printf("%d
    ",k);
    		} else {
    			a=read();
    			b=read();
    			c=read();
    			lca(a,b,c);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    css 正方体
    鼠标放上去,不同的cursor光标类型
    文件上传用到的函数 20150205
    PHP常用正则表达式汇总
    代码练习之 登陆 PHP会话控制 session cookie
    正则表达式全部符号解释
    字典转模型
    Day11 TableView
    Day10
    Day9
  • 原文地址:https://www.cnblogs.com/zhuier-xquan/p/11794496.html
Copyright © 2011-2022 走看看