HDU - 5044(树链剖分)

来源:互联网 发布:股票 数据 阿里云 编辑:程序博客网 时间:2024/05/02 06:45

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;#pragma comment(linker,"/STACK:102400000,102400000")const int maxn = 111111;long long ADD1[maxn],ADD2[maxn];int side,node,wei[maxn],link[maxn],lnode[maxn];//先转化为有根树int fa[maxn];  //每个结点的父节点int w[maxn];  //每个结点的与其父节点的连边在线段树中的位置int top[maxn]; //每条重链中其首节点;int dep[maxn]; //每个节点的深度;int son[maxn]; //每个节点的重儿子int siz[maxn];//vector<int> eson[maxn];int tot,head[maxn*2]; struct Edge{      int to,next; }edge[maxn*2];void addedge(int u,int v){    edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;}void init_dfs(int u){siz[u]=1; son[u]=0;for(int i = head[u];i != -1; i = edge[i].next)if(edge[i].to!=fa[u]){    int v=edge[i].to;    fa[v]=u;    dep[v]=dep[u]+1;    init_dfs(v);    if(siz[son[u]]< siz[v]) son[u]=v;    siz[u]+=siz[v];}}void build_tree(int u,int tp){w[u]=side++; top[u]=tp;  wei[u]=node++;if(son[u]!=0) {       build_tree(son[u],tp);}for(int i = head[u];i != -1; i = edge[i].next)if(edge[i].to!=fa[u]&&edge[i].to!=son[u]){    build_tree(edge[i].to,edge[i].to);}}void init(int n){for(int i=0;i<=n;i++) ADD1[i]=ADD2[i]=0;fa[1]=1; dep[1]=0; top[1]=1;init_dfs(1);side=0; node=1;build_tree(1,1);}int ql,qr,addv;int find(int u,int v){int f1=top[u],f2=top[v];int res=0;while(f1!=f2){    if(dep[f1]<dep[f2]){        swap(f1,f2); swap(u,v);    }    ql=w[f1]; qr=w[u]+1;    ADD2[ql]+=addv;    ADD2[qr]-=addv;    u=fa[f1]; f1=top[u];}if(u==v) return res;if(dep[u]<dep[v]) swap(u,v);ql=w[son[v]]; qr=w[u]+1;ADD2[ql]+=addv;ADD2[qr]-=addv;}void find_node(int u,int v){int f1=top[u],f2=top[v];int res=0;while(f1!=f2){    if(dep[f1]<dep[f2]){        swap(f1,f2); swap(u,v);    }    ql=wei[f1]; qr=wei[u]+1;    ADD1[ql]+=addv;    ADD1[qr]-=addv;    u=fa[f1]; f1=top[u];}if(dep[u]<dep[v]) swap(u,v);ql=wei[v]; qr=wei[u]+1;ADD1[ql]+=addv;ADD1[qr]-=addv;}template <class T>inline bool scan_d(T &ret) {    char c; int sgn;    if(c=getchar(),c==EOF) return 0; //EOF    while(c!='-'&&(c<'0'||c>'9')) c=getchar();    sgn=(c=='-')?-1:1;    ret=(c=='-')?0:(c-'0');    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');    ret*=sgn;    return 1;}inline void out(long long x) {    if(x>9) out(x/10);    putchar(x%10+'0');}int d[maxn][3];int main(){    int T;    int n,kase=1;    scanf("%d",&T);    while(T--){        int Q;        scan_d(n);        scan_d(Q);        int x,y,z;        tot=0;  memset(head,-1,sizeof(head));        for(int i=1;i<n;i++){            scan_d(x);            scan_d(y);            d[i][0]=x; d[i][1]=y; d[i][2]=0;            addedge(d[i][0],d[i][1]);            addedge(d[i][1],d[i][0]);        }        init(n);        for(int i=1;i<n;i++){             if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);        }        char cmd[100];        while(Q--){            int u,v;            scanf("%s",cmd);            scan_d(u);            scan_d(v);            scan_d(addv);            if(cmd[3]=='1'){                find_node(u,v);            }            else find(u,v);        }        for(int i=1;i<=n;i++){            ADD1[i]+=ADD1[i-1];            ADD2[i]+=ADD2[i-1];        }        printf("Case #%d:\n",kase++);        for(int i=1;i<=n;i++){            if(i!=1) printf(" ");            out(ADD1[wei[i]]);        }        printf("\n");        for(int i=1;i<n;i++){            if(i!=1) printf(" ");            out(ADD2[w[d[i][1]]]);        }        printf("\n");    }    return 0;}

本题时间卡的很严;很多地方需注意,输入输出加挂,o(1)的改,o(1)的查,主题方法为树链剖分,实现邻接表的存储用链表形式



0 0
原创粉丝点击