Tree(树链剖分)

Tree

#include<iostream>
#include<cstring>
#include<cmath>
#include<stdlib.h>
#include<cstdio>
# define PI 3.14159265358979323846
#define int long long
#define qc std::ios::sync_with_stdio(false)
using namespace std;
const int maxl=300100;
const int minl=-217483648;
const int mod=1000000;
int n,m,q;
struct edge{
    int to,next;
    edge(){
        to=next=0;
    }
};
struct node
{
    bool z;
    int v,depth,son,zson;
    int pre;//对应重链序的下表
    int top;//头结点位置
    int fa;//父节点
    node(){
        z=false;
        v=0,depth=0,son=0;
        pre=0;
    }
};
struct zro{
    static int cnt;
    static int ni;
    static bool debug_is_off;
    zro(){
        cnt=0;
        ni=0;
        debug_is_off=false;
    }
};
struct seg_t
{
    int r,l,mid;
    int color;
    int lc,rc;
    int tag;
};
int zro::cnt=0;
int zro::ni=0;
bool zro::debug_is_off=false;
edge e[maxl<<1]; zro zr;
node n_[maxl<<1];
seg_t tree[maxl<<2];
int v[maxl<<1], head[maxl<<1],ys[maxl<<1];
void addedge(int u,int v){
    e[++zr.cnt].next=head[u];
    e[zr.cnt].to=v;
    head[u]=zr.cnt;
}

void dfs1(int node,int depth,int f){
    int son=0,ma=0,mi=0;
    n_[node].depth=depth;
    for(int i=head[node];i!=0;i=e[i].next){
        if(e[i].to==f)continue;
        dfs1(e[i].to,depth+1,node);
        son+=n_[e[i].to].son+1;
        if(n_[e[i].to].son>=ma){
            ma=n_[e[i].to].son,mi=e[i].to;
        }
    }
    n_[mi].z=true;
    n_[node].zson=mi;
    n_[node].son=son;
    n_[node].fa=f;
}
void dfs2(int node,int top){
    ys[++zr.ni]=node;
    n_[node].pre=zr.ni;
    int z=n_[node].zson;
    if(node==1)n_[node].top=node;
    else if(n_[node].z)n_[node].top=n_[n_[node].fa].top;
    else n_[node].top=node;
    if(z)dfs2(z,node);
    for(int i=head[node];i!=0;i=e[i].next){
        if(e[i].to==n_[node].fa||n_[e[i].to].z)continue;
        dfs2(e[i].to,node);
    }
}
void pushdown(int k){
 // cout<<"pushdown: "<<k<<" tag: "<<tree[k].tag<<endl;
    if(tree[k].tag!=-1){
        if(tree[k].l==tree[k].r){
            n_[ys[tree[k].l]].v=tree[k].tag;
            tree[k].lc=tree[k].rc=tree[k].tag;
            // cout<<"kkkkkkkkkkkkkkkindex"<<tree[k].l<<endl;
            tree[k].tag=-1;
            return;
        }
        tree[k<<1|1].color=tree[k<<1].color=1;
        tree[k<<1|1].tag=tree[k<<1].tag=tree[k].tag;
        tree[k<<1|1].lc=tree[k<<1|1].rc=tree[k<<1].lc=tree[k<<1].rc=tree[k].tag;
        tree[k].tag=-1;
        //cout<<"pushdown: "<<tree[k<<1].lc<<endl;
    }
}
int tree_onclo(int k,int index){
    //if(index==1)cout<<"fuckwhyerror:"<<k<<endl;
    if(tree[k].l==tree[k].r){
      //  cout<<" index"<<index<<" v "<<tree[k].lc<<endl;
        return tree[k].lc;
    }
    pushdown(k);
    int mid=(tree[k].l+tree[k].r)>>1;
    if(index<=mid)return tree_onclo(k<<1,index);
    if(index>mid)return tree_onclo(k<<1|1,index);
    return 0;
}
void pushup(int k){
    if(tree[k<<1].rc==tree[k<<1|1].lc)tree[k].color=tree[k<<1].color+tree[k<<1|1].color-1;
    else tree[k].color=tree[k<<1].color+tree[k<<1|1].color;
    tree[k].lc=tree[k<<1].lc;
    tree[k].rc=tree[k<<1|1].rc;
}

void build(int k,int l,int r){
    tree[k].l=l;tree[k].r=r,tree[k].tag=-1;
    if(l==r)
    {   
        tree[k].color=1;
        tree[k].lc=tree[k].rc=n_[ys[l]].v;
       // cout<<" l "<<l<<" r "<<r<<" v "<<tree[k].lc<<endl;
        tree[k].tag=-1;
        //cout<<tree[k].tag<<endl;
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    pushup(k);
}

void tree_update(int k,int l,int r,int v){
    //cout<<"tree_update: "<<" k :"<<k<<" l :"<<tree[k].l<<" r: "<<tree[k].r<<" v: "<<v<<endl;
   // cout<<l<<"<--->"<<r<<endl;
    if(tree[k].r<=r&&tree[k].l>=l){
        tree[k].color=1;
        tree[k].lc=tree[k].rc=v;
        tree[k].tag=v;
       // cout<<tree[k].l<<"--"<<tree[k].r<<endl;
      //   cout<<"tree["<<k<<"].tag==";
      //   cout<<tree[k].tag<<endl;
        return;
    }
    pushdown(k);
    int mid=(tree[k].l+tree[k].r)>>1;
    if(l<=mid)tree_update(k<<1,l,r,v);
    if(r>mid)tree_update(k<<1|1,l,r,v);
    pushup(k);
}
int tree_color(int k,int l,int r){
    if(tree[k].l>=l&&tree[k].r<=r){
        return tree[k].color;
    }
    pushdown(k);
    int mid=(tree[k].l+tree[k].r)>>1;
    int color=maxl;
    if(l<=mid)color=min(color,tree_color(k<<1,l,r));
    if(r>mid)color=min(color,tree_color(k<<1|1,l,r));
    return color;
}

int find_color(int l,int r){
    int maxnum=0;
    if(n_[l].top==n_[r].top)maxnum= tree_color(1,min(n_[l].pre,n_[r].pre),max(n_[l].pre,n_[r].pre));
    else if(n_[n_[l].top].depth>=n_[n_[r].top].depth){
        maxnum= find_color(l,n_[l].top)+find_color(n_[n_[l].top].fa,r);
        int topc=tree_onclo(1,n_[n_[l].top].pre),fac=tree_onclo(1,n_[n_[n_[l].top].fa].pre);
       // cout<<"l-------"<<n_[n_[l].top].pre<<"/"<<n_[n_[n_[l].top].fa].pre<<endl;
      //  cout<<"twoclo:"<<topc<<"-----"<<fac;
        if(topc==fac)maxnum-=1;
    }
    else{
        maxnum= find_color(r,n_[r].top)+find_color(l,n_[n_[r].top].fa);
        int topc=tree_onclo(1,n_[n_[r].top].pre),fac=tree_onclo(1,n_[n_[n_[r].top].fa].pre);
        //cout<<"l-------"<<n_[n_[r].top].pre<<"/"<<n_[n_[n_[r].top].fa].pre<<endl;
      //  cout<<"twoclo:"<<topc<<"-----"<<fac;
        if(topc==fac)maxnum-=1;
    }
  //  cout<<"findc "<<l<<"---"<<r<<" =="<<maxnum<<endl;
    return maxnum;
}
void update(int l,int r,int v){
    int il=n_[l].pre,ir=n_[r].pre;
    tree_update(1,min(il,ir),max(il,ir),v);
}
void init(){
    memset(e,0,sizeof(e));
    memset(n_,0,sizeof(n));
    memset(tree,0,sizeof(tree));
    memset(v,0,sizeof(v));
    memset(head,0,sizeof(head));
    memset(ys,0,sizeof(ys));
    zr.cnt=0;
    zr.ni=0;
}
signed main(){
   // qc;
        while(cin>>n>>q){
            init();
        for(int i=1;i<=n;i++){
            scanf("%d",&n_[i].v);
        }
        for(int i=1;i<n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            addedge(a,b);
            addedge(b,a);
        }
        dfs1(1,1,0);
        dfs2(1,0);
        build(1,1,n);
     //   debug();
        for(int i=1;i<=q;i++){
            char c[2];
            int a,b,v;
            scanf("%s",c);
            scanf("%d%d",&a,&b);
            if(c[0]=='C'){
                scanf("%d",&v);
                update(a,b,v);
            }
            else {
                int ans=find_color(a,b);
                printf("%d\n",ans);
            }
        }
        }
    /*
8
1 2 1 3
2 4 2 5
3 6 3 7
4 8
1 2 3 4 5 6 7 8
     */
    
    
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容