hdu5044(神姿势+树链剖分)

Tree

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 533    Accepted Submission(s): 106


Problem Description
You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N

There are N - 1 edges numbered from 1 to N - 1.

Each node has a value and each edge has a value. The initial value is 0.

There are two kind of operation as follows:

● ADD1 u v k: for nodes on the path from u to v, the value of these nodes increase by k.

● ADD2 u v k: for edges on the path from u to v, the value of these edges increase by k.

After finished M operation on the tree, please output the value of each node and edge.
 

Input
The first line of the input is T (1 ≤ T ≤ 20), which stands for the number of test cases you need to solve.

The first line of each case contains two integers N ,M (1 ≤ N, M ≤10 5),denoting the number of nodes and operations, respectively.

The next N - 1 lines, each lines contains two integers u, v(1 ≤ u, v ≤ N ), denote there is an edge between u,v and its initial value is 0.

For the next M line, contain instructions “ADD1 u v k” or “ADD2 u v k”. (1 ≤ u, v ≤ N, -10 5 ≤ k ≤ 10 5)
 

Output
For each test case, print a line “Case #t:”(without quotes, t means the index of the test case) at the beginning.

The second line contains N integer which means the value of each node.

The third line contains N - 1 integer which means the value of each edge according to the input order.
 

Sample Input
  
  
2 4 2 1 2 2 3 2 4 ADD1 1 4 1 ADD2 3 4 2 4 2 1 2 2 3 1 4 ADD1 1 4 5 ADD2 3 2 4
 

Sample Output
  
  
Case #1: 1 1 0 1 0 2 2 Case #2: 5 0 0 5 0 4 0
 

Source
 

Recommend
hujie   |   We have carefully selected several similar problems for you:   5052  5051  5050  5049  5048 

比赛时候问了句:卡时限真的好吗?

回答:卡的是姿势~

看来姿势真的很重要啊,学习了。。。。。

不说了,无力吐槽。

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#define maxn 100010
#define INF 0x7ffffff
#define efor(u) for(int i=head[u];i!=-1;i=e[i].next)
#define ll long long
using namespace std;
map<pair<int,int> ,int> q;
map<pair<int,int> ,int>::iterator it;
struct edge{int v,next;}e[2*maxn];
int head[maxn],tol;
int size[maxn],pre[maxn],son[maxn],dep[maxn],top[maxn],w[maxn],tw[maxn];
ll ans[maxn];
pair<int,int> p[maxn];
int n,m,va[maxn],tn;
template<class T> inline void readint(T& x) {
      char c;
      int mul = 1;
      while((c = getchar()) != EOF){
         if(c == '-')mul = -1;
         if(c >= '0' && c <= '9'){
              x = c-'0';
              break;
         }
      }
      if(c == EOF){x = EOF;return;}
      while(c = getchar()){
          if(c >= '0' && c <= '9'){
              x = (x<<1)+(x<<3)+(c-'0');
          }else break;
      }
      x *= mul;
}
void init(){
    q.clear();
    tol=0;
    memset(head,-1,sizeof head);
}
void addedge(int u,int v){
    e[tol].v=v,e[tol].next=head[u],head[u]=tol++;
}
void tree_init(){
    tn=0,dep[1]=0;
}
void dfs(int u,int fa){
    size[u]=1,son[u]=0,pre[u]=fa;
    efor(u){
       int v=e[i].v;
       if(v!=fa){
          dep[v]=dep[u]+1;
          dfs(v,u);
          size[u]+=size[v];
          if(size[v]>size[son[u]]) son[u]=v;
       }
    }
}
void build_tree(int x,int f){
    q[make_pair(min(x,pre[x]),max(x,pre[x]))]=tn;
    //cout<<x<<" "<<pre[x]<<"=>"<<tn<<endl;
    w[x]=++tn,tw[tn]=x,top[x]=f;
    if(son[x]>0) build_tree(son[x],f);
    efor(x){
        int v=e[i].v;
        if(v!=pre[x]&&v!=son[x]) build_tree(v,v);
    }
}

ll A[maxn],B[maxn];
void read(){
    readint(n),readint(m);
    for(int i=1;i<n;i++){
        readint(p[i].first),readint(p[i].second);
        addedge(p[i].first,p[i].second),addedge(p[i].second,p[i].first);
        if(p[i].first>p[i].second) swap(p[i].first,p[i].second);
    }
}
void gao(int x,int y,int z,int t){
    if(t){
        while(top[x]!=top[y]&&x!=y){
            if(dep[top[x]]>dep[top[y]]) swap(x,y);
            //cout<<w[top[y]]-1<<" "<<w[y]-1<<" "<<z<<endl;
            B[w[top[y]]-1]+=z;
            B[w[y]]-=z;
            y=pre[top[y]];
        }
        if(x==y) return;
        if(dep[x]<dep[y]){
            //cout<<w[x]<<" "<<w[y]-1<<" "<<z<<endl,
            B[w[x]]+=z;
            B[w[y]]-=z;
        }else{ //cout<<w[y]<<" "<<w[x]-1<<" "<<z<<endl,
            B[w[y]]+=z;
            B[w[x]]-=z;
        }
    }else{
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            //cout<<w[top[x]]<<" "<<w[x]+1<<endl;
            A[w[top[x]]]+=z;
            A[w[x]+1]-=z;
            x=pre[top[x]];
        }
        if(dep[x]<dep[y]) swap(x,y);
        //cout<<w[y]<<" "<<w[x]+1<<endl;
        A[w[y]]+=z;
        A[w[x]+1]-=z;
    }
}
void solve(int ca){
    printf("Case #%d:\n",ca);
    tree_init();
    dfs(1,1);
    build_tree(1,1);
    memset(A,0,sizeof A);
    memset(B,0,sizeof B) ;
    char s[10];
    int x,y,z;
    for(int i=0;i<m;i++){
        scanf("%s",s);
        readint(x),readint(y),readint(z);
        if(x>y) swap(x,y);
        if(s[3]=='1'){
            gao(x,y,z,0);
        }else{
            gao(x,y,z,1);
        }
    }
    for(int i=1;i<=n;i++){
        A[i]+=A[i-1];
        ans[tw[i]]=A[i];
    }
    for(int i=1;i<=n;i++){
        if(i>1) printf(" ");
        printf("%I64d",ans[i]);
    }
    printf("\n");
    for(int i=1;i<n;i++){
        B[i]+=B[i-1];
    }
    for(int i=1;i<n;i++){
        ans[i]=B[q[p[i]]];
    }
    for(int i=1;i<n;i++){
        if(i>1) printf(" ");
        printf("%I64d",ans[i]);
    }
    printf("\n");
}
int T;
int main(){
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++){
        init();
        read();
        solve(ca);
    }
    return 0;
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值