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;
}

猜你喜欢

转载自www.cnblogs.com/zhuier-xquan/p/11794496.html