BZOJ-1036: [ZJOI2008]树的统计Count(轻重树链剖分 LCT)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036

时间:

LCT(O((n+m) log n)):

9922720e0cf3d7cad689985bf01fbe096b63a9a4.jpg.png

树链剖分(O((n+m) log^2 n)):

b21bb051f81986184e5848a948ed2e738bd4e684.jpg.png

代码(第一次尝试写轻重树链剖分,O(n log^2 n)的复杂度还可以。。下次再来写块状树,lct的代码链接(https://www.jianshu.com/p/6090162a7759 度娘一次不给贴太长的染色代码,只能代码另发一次了。。。)函数式线段树MLE了,空间O((n log n + q) log n)各种巨大啊 TAT):

(树链的太长贴不了染色的。。。)

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <cstdlib>

using namespace std;

#define MAXN 30001

#define inf 0x7fffffff

#define MAXM 200001

#define clear(x) memset(x,0,sizeof(x))

struct edge{

    int t;

    edge *next;

    edge (){

        next=NULL;

    }

}*he[MAXN];

int n,m,par[MAXN],Si[MAXN],Ch[MAXN],Que[MAXM][3],Index=0,Num=0,Id[MAXN],Arr[MAXN],Pos[MAXN],Fir[MAXN],Lca[MAXM],fat[MAXN],w[MAXN];

bool f[MAXN];

void AddEdge(int s,int t){edge *p=new(edge);p->t=t;p->next=he[s];he[s]=p;}

void Dfs_Si(int v){

    f[v]=false;

    Si[v]=1;

    int maxSi=0;

    for(edge *p=he[v];p;p=p->next){

        if(f[p->t]){

            par[p->t]=v;

            Dfs_Si(p->t);

            Si[v]+=Si[p->t];

            if(Si[p->t]>maxSi){

                maxSi=Si[p->t];

                Ch[v]=p->t;

            }

        }

    }

}

void Heavy_Edge(int v,bool flag){

    if(flag) Fir[++Index]=v;

    Id[v]=Index;

    Arr[Pos[v]=++Num]=v;

    f[v]=false;

    if(Ch[v])Heavy_Edge(Ch[v],false);

    for(edge *p=he[v];p;p=p->next){

        if(f[p->t]&&p->t!=Ch[v]){

            Heavy_Edge(p->t,true);

        }

    }

}

struct lca_type {

    int t,r;

    lca_type *next;

}*Fro[MAXN];

void Insert(int s,int t,int r){

    lca_type *p=new(lca_type);

    p->t=t;p->r=r;p->next=Fro[s];Fro[s]=p;

}

int Find(int v){

    int i,j=v;

    for(i=v;fat[i];i=fat[i]);

    while(fat[j]){

        int k=fat[j];

        fat[j]=i;

        j=k;

    }

    return i;

}

void Tarjan(int v){

    f[v]=false;

    for(lca_type *p=Fro[v];p;p=p->next)if(!f[p->t])  Lca[p->r]=Find(p->t);

    for(edge *p=he[v];p;p=p->next)

        if(f[p->t]){Tarjan(p->t);fat[Find(p->t)]=v;}

}

struct node{

    int l,r,Max,Sum;

} T[MAXN*3];

void Build_SegT(int l,int r,int t){

    T[t].l=l,T[t].r=r;

    if(l==r){

        T[t].Max=T[t].Sum=w[Arr[l]];

        return;

    }

    Build_SegT(l,(l+r)>>1,t<<1);

    Build_SegT(((l+r)>>1)+1,r,(t<<1)^1);

    T[t].Max=max(T[t<<1].Max,T[(t<<1)^1].Max);

    T[t].Sum=T[t<<1].Sum+T[(t<<1)^1].Sum;

}

void INIT(){

    scanf("%d",&n);

    memset(he,0,sizeof(he));

    for(int i=0;i++<n-1;){

        int s,t;

        scanf("%d%d",&s,&t);

        AddEdge(s,t),AddEdge(t,s);

    }

    clear(par),clear(Ch);

    memset(f,true,sizeof(f));

    Dfs_Si(1);

    memset(f,true,sizeof(f));

    Heavy_Edge(1,true);

    for(int i=0;i++<n;)scanf("%d",&w[i]);

    memset(Fro,0,sizeof(Fro));

    scanf("%d",&m);

    for(int i=0;i++<m;){

        char s[20];

        scanf("%s%d%d",&s,&Que[i][1],&Que[i][2]);

        if(s[0]=='C') Que[i][0]=0

        ;else{

            if(s[1]=='M') Que[i][0]=1

            ;  else Que[i][0]=2;

            Insert(Que[i][1],Que[i][2],i);

            Insert(Que[i][2],Que[i][1],i);

        }

    }

    memset(f,true,sizeof(f));clear(fat);

    Tarjan(1);

    Build_SegT(1,n,1);

}

void Change(int v,int u,int t){

    if(T[t].l==T[t].r){

        T[t].Sum=T[t].Max=u;

        return;

    }

    if(v<=((T[t].l+T[t].r)>>1))Change(v,u,t<<1)

    ;  else Change(v,u,(t<<1)^1);

    T[t].Sum=T[t<<1].Sum+T[(t<<1)^1].Sum;

    T[t].Max=max(T[t<<1].Max,T[(t<<1)^1].Max);

}

int Max(int l,int r,int t){

    if(T[t].l==l&&T[t].r==r)return T[t].Max;

    int mid=(T[t].l+T[t].r)>>1;

    if(r<=mid)return Max(l,r,t<<1);

    if(l>mid)return Max(l,r,(t<<1)^1);

    return max(Max(l,mid,t<<1),Max(mid+1,r,(t<<1)^1));

}

int Sum(int l,int r,int t){

    if(T[t].l==l&&T[t].r==r)return T[t].Sum;

    int mid=(T[t].l+T[t].r)>>1;

    if(r<=mid)return Sum(l,r,t<<1);

    if(l>mid)return Sum(l,r,(t<<1)^1);

    return Sum(l,mid,t<<1)+Sum(mid+1,r,(t<<1)^1);

}

int GM(int v,int u){

    int rec=-inf;

    while(1){

        if(Id[v]==Id[u])return max(rec,Max(Pos[u],Pos[v],1))

        ; else{rec=max(rec,Max(Pos[Fir[Id[v]]],Pos[v],1));v=par[Fir[Id[v]]];}

    }

}

int GS(int v,int u){

    int rec=0;

    while(1){

        if(Id[v]==Id[u])return rec+Sum(Pos[u],Pos[v],1);  else rec+=Sum(Pos[Fir[Id[v]]],Pos[v],1),v=par[Fir[Id[v]]];

    }

}

void Solve(){

    for(int i=0;i++<m;){

        if(!Que[i][0]){

            Change(Pos[Que[i][1]],Que[i][2],1);

            w[Que[i][1]]=Que[i][2];

        }else{

            if(Que[i][0]==1)printf("%d\n",max(GM(Que[i][1],Lca[i]),GM(Que[i][2],Lca[i])));  else printf("%d\n",GS(Que[i][1],Lca[i])+GS(Que[i][2],Lca[i])-w[Lca[i]]);

        }

    }

}

int main(){

    INIT();

    Solve();

    return 0;

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容

  • 一年级语文上册生字表 生字表一(共400字) 啊(ā)爱(ài)安(ān)岸(àn)爸(bà)八(bā)巴(bā)...
    meychang阅读 2,789评论 0 6
  • 列表和字典有什么不同? 列表是有序排列的一些物件,而字典是将一些物件(keys)对应到另外一些物件(values)...
    庵下桃花仙阅读 277评论 0 0
  • 明明白白的喜欢, 有些厌倦。 多想念, 多可怜。 自始自终都明白, 留不住的心欢, 一遍遍, 一遍遍浪费情感。 多...
    雨洗阅读 262评论 0 1
  • 一辆像是脱缰的野马的大货车向我直冲过来,我看了看副驾驶的妻子:“我爱你。” 嘭!看着眼前的天花板,...
    祈安居士阅读 272评论 0 0