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;
}
然后差分约束还是没做完,又去做了还算简单的
这个题中,我莫名的和所有题解的建边都不一样。
但是要注意到的是一定要在相邻两个点之间连一条权值为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;
}