Accept: 9    Submit: 32
Time Limit: 2000 mSec    Memory Limit : 32768 KB

 Problem Description

给定一棵n个节点以1为根的树,初始每个节点的值为0,现在我们要在树上进行一些操作,操作有两种类型。

1 x val 表示对以x为根的子树的每个点进行加权操作(我们定义每个节点的深度为每个节点到根1的距离),如果 y是以x为根的子树中的点那么 y节点的权值增加 ((dep[y]-dep[x])%k+1)*val 其中dep[y]表示y节点的深度,k为一个常数(1<=k<=5)

2 x 查询当前x节点的权值。

 Input

首先输入一个整数T 表示数据的组数,每组数据 第一行有3个整数 n ,m, k(1<=n,m<=50000, 1<=k<=5) 。n表示节点数,m表示操作数,k表示如题目描述的常数。

接下去n-1行描述一棵树。接下去m行每行表示 一个操作 有两种类型1 x val 表示第一种类型 2 x 表示第二种类型。(1<=x<=n,1<=val<=100)

 Output

每组数据首先输出 Case#x: 表示第x组数据 x从1开始。接下去对于每组数据中的每个查询操作输出查询结果。(具体输出格式看样例)

 Sample Input

1
5 7 2
1 2
2 4
2 5
1 3
 
 
1 2 3
1 1 2
2 1
2 2
2 3
2 4
2 5

 Sample Output

Case#1:
2
7
4
8
8
大致思路:首先树链剖分一下,然后用树状数组或者线段树维护区间更新,但是((dep[y]-dep[x])%k+1)*val这种该怎么更新呢,,看到k很小最大只有5,可以想到用5棵线段树或者树状数组来维护。首先每个节点的深度dep确定后 每隔k个深度权值增加的是相等的。这样的话 就可以把所有的点对应到 k个树状数组 上去。然后就是树状数组经典的区间更新单点查询操作了。
 #include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-;
const int maxn = 5e4+;
struct
{
int to,next;
} e[maxn<<];
int tot,head[maxn];
void add_edge(int x,int y)
{
e[tot].to = y;
e[tot].next = head[x];
head[x] = tot++;
}
int siz[maxn],son[maxn],fa[maxn],dep[maxn];
void dfs(int root)
{
siz[root] = ;
son[root] = ;
for (int i = head[root]; ~i; i = e[i].next)
{
if (fa[root] != e[i].to)
{
fa[e[i].to] = root;
dep[e[i].to] = dep[root] + ;
dfs(e[i].to);
if (siz[e[i].to] > siz[son[root]])
son[root] = e[i].to;
siz[root] += siz[e[i].to];
}
}
}
int pos[maxn],top[maxn],L[maxn],R[maxn],bj1,bj2,idx;
void build (int root,int father)
{
pos[root] = ++idx;
top[root] = father;
L[root] = root;
R[root] = root;
if (son[root] > )
{
bj1 = son[root];
build(son[root],top[root]);
L[root] = bj1;
}
bool flag = ;
for (int i = head[root]; ~i; i = e[i].next)
{
flag = ;
if (fa[root] != e[i].to && son[root] != e[i].to)
bj2 = e[i].to,build(e[i].to,e[i].to);
else if (siz[root] == )
bj2 = root;
}
if (flag)
R[root] = bj2;
}
int lowbit(int x)
{
return x & -x;
}
int c[][maxn],n;
void add(int x,int d,int k)
{
while (x <= n)
{
c[k][x] += d;
x += lowbit(x);
}
}
int sum(int x,int k)
{
int ans = ;
while (x > )
{
ans += c[k][x];
x -= lowbit(x);
}
return ans;
}
void init()
{
int root = ;
tot = idx = ;
dep[root] = fa[root] = ;
memset(head,-,sizeof(head));
memset(siz,,sizeof(siz));
memset(c,,sizeof(c));
for (int i = ; i < n; i++)
{
int u,v;
scanf ("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(root);
build(root,root);
}
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int t,cas = ;
scanf ("%d",&t);
while (t--)
{
printf("Case#%d:\n",cas++);
int k,m;
scanf ("%d%d%d",&n,&m,&k);
init();
for (int i = ; i < m; i++)
{
int op,x,val;
scanf ("%d%d",&op,&x);
if (op == )
{
scanf ("%d",&val);
for (int j = ; j < k; j++)
{
int tmp = (j + ) * val;
int l = pos[x];
int r = pos[R[x]];
add(pos[x], tmp,((dep[x] + )%k + j)%k);
add(pos[R[x]] + , -tmp,((dep[x] + )%k + j)%k);
}
}
if (op == )
{
printf("%d\n",sum(pos[x],(dep[x]-dep[] + ) % k));
}
}
}
return ;
}

FZU2176---easy problem (树链剖分)的更多相关文章

  1. FZOJ 2176 easy problem ( 树链剖分 )

    pid=2176" target="_blank">题目链接~~> 做题感悟:感觉做多了树链剖分的题目,有很多是树链剖分 + 想法.. 解题思路: 这题非常明 ...

  2. P1001 A+B Problem (树链剖分)

    这题考验我们构造模型的能力. 考虑构造一棵树,树上有3个节点,节点1和节点2连一条权值为a的边,节点1和节点3连一条权值为b的边,显然答案就是节点2到节点3的最短路径. 但这样还不够.考虑加法的性质, ...

  3. HDU 5293 Train chain Problem - 树链剖分(树状数组) + 线段树+ 树型dp

    传送门 题目大意: 一颗n个点的树,给出m条链,第i条链的权值是\(w_i\),可以选择若干条不相交的链,求最大权值和. 题目分析: 树型dp: dp[u][0]表示不经过u节点,其子树的最优值,dp ...

  4. Hdu 5052 Yaoge’s maximum profit(树链剖分)

    题目大意: 给出一棵树.每一个点有商店.每一个商店都有一个价格,Yaoge每次从x走到y都能够在一个倒卖商品,从中得取利益.当然,买一顶要在卖之前.可是没次走过一条路,这条路上的全部商品都会添加一个v ...

  5. HDU 4729 An Easy Problem for Elfness(树链剖分边权+二分)

    题意 链接:https://cn.vjudge.net/problem/HDU-4729 给你n个点,然你求两个点s和t之间的最大流.而且你有一定的钱k,可以进行两种操作 1.在任意连个点之间建立一个 ...

  6. (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。

    Problem Description   Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are ...

  7. Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组

    Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations ...

  8. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  9. USACO 2015 December Contest, Platinum Problem Max Flow【树链剖分】

    题意比较难理解,就是给你n个点的树,然后给你m个修改操作,每一次修改包括一个点对(x, y),意味着将x到y所有的点权值加一,最后问你整个树上的点权最大是多少. 比较裸的树链剖分了,感谢Haild的讲 ...

随机推荐

  1. Tomcat jdbc pool配置

    Tomcat jdbc pool是apache在tomcat7版本中启用的新连接池,用它来解决以往DBCP无法解决的一些问题. Tomcat jdbc pool的优点: (1)    tomcat j ...

  2. C#中的序列化与反序列化

    眼看XX鸟的课程关于C#的知识点就要学完了,翻看网络中流传的教程还是发现了一个课程中没有讲到的知识点:序列化与反序列化 无奈还是了解一下并操作一番,以备后用吧 介绍:就是将对象信息转化为二进制信息以便 ...

  3. hdu 2689

    hdu 2689 超级大水题....两种代码都过了,开始以为n^2会tle,后来竟然过了...汗 注意下cin写在while里面,就可以了 #include <iostream> usin ...

  4. file控件change事件触发问题

    最近,项目中需要用到一个图片上传的功能,我用的file控件来选取图片文件,然后利用js读取文件来预览图片,最后再根据用户的操作来决定是否上传文件. 其中碰到了一个奇怪的问题:在选取完第一张图片,并上传 ...

  5. springxml配置构造函数入参

    springxml配置构造函数入参有深入的理解 集合mockito创建对象的方法.功能等同于创建对象的代码. spring配置文件中定义bean的好处 便于集中管理,系统任何地方都可以引用使用.如果不 ...

  6. mysql explain 命令解释

    转载http://bzyyc.happy.blog.163.com/blog/static/6143064720115102551554/ key实 际使用的索引.如果为NULL,则没有使用索引.很少 ...

  7. jQuery验证框架 .

          目录视图 摘要视图 订阅 “程序人生”中国软件开发者职业生涯调查     CSDN社区“三八节”特别活动      开发者职业生涯调查之未来 jQuery验证框架 分类: JQuery 2 ...

  8. WPF Mahapps.Metro 设置主题样式

    /// <summary> /// 设置App样式 /// </summary> /// <param name="accentName">窗口 ...

  9. android WIFI的一些属性

    package com.example.wifitest; import java.util.List; import android.content.Context; import android. ...

  10. Android基本组件-Activity

    什么是Activity 在Android程序中,每个Activity继承自android.app.Activity, 有一个与之对应的xml布局文件, 一个界面对应一个Activity, 每个Acti ...