D4 HL 数据结构

今天都不会;

太神仙了 我回来再补吧

丢一个树剖+线段树表示我没白坐一天;

https://www.luogu.org/problemnew/show/P2486

//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<queue>
#include<deque>
#include<vector>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#include<cstdlib>
using namespace std;
#define N 100010 
template<typename T>inline void read(T &x)
{
    x=0;
    register int f=1;
    register char ch=getchar();
    while (!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

int n,m,tot,sz;
int v[N],vis[N],pl[N],lin[N],belong[N],son[N],d[N],f[N][18];

struct gg {
    int x,y,next;
}a[N<<1];

struct pink {
    int l,r,lc,rc,s,tag;
}t[4*N];

inline void add(int x,int y) {
    a[++tot].x=x;
    a[tot].y=y;
    a[tot].next=lin[x];
    lin[x]=tot;
}

inline void dfs1(int x) {
    vis[x]=son[x]=1;
    for(int i=1;i<=17;i++) {
        if(d[x]<(1<<i))break;
        f[x][i]=f[f[x][i-1]][i-1];
    }
    for(int i=lin[x];i;i=a[i].next) {
        int y=a[i].y;
        if(vis[y])continue;
        d[y]=d[x]+1;
        f[y][0]=x;
        dfs1(y);
        son[x]+=son[y];
    }    
}

inline void dfs2(int x,int chain) {//当前节点 该链顶端 
    pl[x]=++sz; belong[x]=chain;//pl保存当前dfs序中对应节点编号;belong当前节点记录所熟链的顶端节点; 
    int k=0;
    for(int i=lin[x];i;i=a[i].next) {
        int y=a[i].y;
        if(f[x][0]!=y&&son[k]<son[y])
            k=y;
    }
    if(!k) return ;
    dfs2(k,chain);
    for(int i=lin[x];i;i=a[i].next) {
        int y=a[i].y;
        if(k!=a[i].y&&d[y]>d[x]) {
            dfs2(y,y);//一个点位于轻链底端 那么链顶还是自己; 
        }
    }
}

inline void build(int p,int l,int r) {
    t[p].l=l; t[p].r=r; 
    t[p].tag=-1; t[p].s=1;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(p<<1,l,mid); build(p<<1|1,mid+1,r);
} 

inline void pushup(int k) {
    t[k].lc=t[k<<1].lc;t[k].rc=t[k<<1|1].rc;
    if(t[k<<1].rc^t[k<<1|1].lc) t[k].s=t[k<<1].s+t[k<<1|1].s;
    else t[k].s=t[k<<1].s+t[k<<1|1].s-1;
}

inline void pushdown(int k) {
    int tmp=t[k].tag;t[k].tag=-1;
    if(tmp==-1||t[k].l==t[k].r)    return;
    t[k<<1].s=t[k<<1|1].s=1;
    t[k<<1].tag=t[k<<1|1].tag=tmp;
    t[k<<1].lc=t[k<<1].rc=tmp;
    t[k<<1|1].lc=t[k<<1|1].rc=tmp;
}

inline int lca(int x,int y) {
    if(d[x]>d[y]) swap(x,y);
    for(int i=17;i>=0;--i) {
        if(d[f[y][i]]>=d[x]) 
            y=f[y][i];
    }
    if(x==y) return x;
    for(int i=17;i>=0;i--) {
        if(f[y][i]!=f[x][i]) {
            y=f[y][i]; x=f[x][i];
        }
    }
    return f[x][0];
}

inline void change(int k,int x,int y,int c) {
    pushdown(k);
    int l=t[k].l,r=t[k].r;
    if(l==x&&r==y)
    {    
        t[k].lc=t[k].rc=c;
        t[k].s=1;t[k].tag=c;
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=y) change(k<<1,x,y,c);
    else if(mid<x) change(k<<1|1,x,y,c);
    else {
        change(k<<1,x,mid,c);
        change(k<<1|1,mid+1,y,c);
    }
    pushup(k);
}

int ask(int k,int x,int y) {
    pushdown(k);
    int l=t[k].l,r=t[k].r;
    if(l==x&&r==y)return t[k].s;
    int mid=(l+r)>>1;
    if(mid>=y)return ask(k<<1,x,y);
    else if(mid<x)return ask(k<<1|1,x,y);
    else {
        int tmp=1;
        if(t[k<<1].rc^t[k<<1|1].lc)tmp=0;
        return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y)-tmp;
    }
}

int getc(int k,int x) {
    pushdown(k);
    int l=t[k].l,r=t[k].r;
    if(l==r)    return t[k].lc;
    int mid=(l+r)>>1;
    if(x<=mid)    return getc(k<<1,x);
    else return getc(k<<1|1,x);
}

inline int slovesum(int x,int y) {
    int sum=0;
    while(belong[x]!=belong[y]) {
        sum+=ask(1,pl[belong[x]],pl[x]);
        if(getc(1,pl[belong[x]])==getc(1,pl[f[belong[x]][0]])) sum--;
        x=f[belong[x]][0];
    }
    sum+=ask(1,pl[y],pl[x]);
    return sum;
}

inline void slovechange(int x,int y,int c) {
    while(belong[x]!=belong[y]) {
        change(1,pl[belong[x]],pl[x],c);
        x=f[belong[x]][0];
    }
    change(1,pl[y],pl[x],c);
}

inline void init() {
    read(n); read(m);
    for(int i=1;i<=n;i++) {
        read(v[i]);
    }
    for(int i=1,x,y;i<n;i++) {
        read(x); read(y);
        add(x,y); add(y,x);
    }
}

inline void slove() {
    int a,b,c;
    d[1]=1;
    dfs1(1);
    dfs2(1,1);
    build(1,1,n);
    for(int i=1;i<=n;i++) {
        change(1,pl[i],pl[i],v[i]);
    }
    for(int i=1;i<=m;i++) {
        char ch[2];
        scanf("%s",ch);
        if(ch[0]=='Q') {
            read(a); read(b);
            int t=lca(a,b);
            printf("%d\n",slovesum(a,t)+slovesum(b,t)-1);
        }
        else {
            read(a); read(b); read(c);
            int t=lca(a,b);
            slovechange(a,t,c); slovechange(b,t,c); 
        }
    }
}

int main() {
//    freopen("a.in","r",stdin);
//    freopen("a.out","w",stdout);
    init();
    slove();
    return 0;
}
View Code
posted @ 2019-07-10 07:23  Tyouchie  阅读(204)  评论(0编辑  收藏  举报