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\n",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\n");
	else
		printf("No\n");
	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\n");
		else 
			printf("N0\n");
	}
	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\n",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\n");
	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\n",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\n");
			else 
				printf("%d\n",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\n",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\n",k);
		} else {
			a=read();
			b=read();
			c=read();
			lca(a,b,c);
		}
	}
	return 0;
}
posted @ 2019-11-04 20:21  Sweetness  阅读(155)  评论(0编辑  收藏  举报