Codechef Observing the Tree
Chef gives you a tree, consisting of N nodes. The nodes are numbered from 1 to N, and each node has an integer, which is equal to 0 initially. Then, Chef asks you to perform M queries.
The first type of queries is changing: here, you are given integers X, Y, A and B. Add Ato the integer, associated with the node X, then add A+B to the integer, associated with the second node on the way from X to Y, then add A+2*B to the integer, associated with the third node on the way from X to Y, and so on. As you know, there is only one simple path from X to Y.
The second type of queries is a question: here, you are given integers X and Y. Output the sum of all integers, associated with nodes on the way from X to Y.
The third type of queries is a rollback: here, you are given an integer X. All the integers associated with the nodes return to the state after the X-th changing query. If X is 0, then all of them become equal to zero, as in the very beginning.
Input
The first line of an input consists of two integers - N and M.
Then, N−1 lines follow. These N−1 lines describe the tree structure. Each line consists of two integers - X and Y, and that means that there is an edge between node X and node Y.
Then, M lines follow. A single line denotes a single query, which has one of the following forms: (See the sample for the detailed explanation)
- c X1 Y1 A B - changing query,
- q X1 Y1 - question query,
- l X1 - rollback query.
As you can see, the numbers X and Y aren't given to you directly. For the rollbackquery, actual number X will be equal to (X1+lastans) modulo (total number ofchanging queries before this query + 1). For the changing and question queries, Xwill be equal to ((X1+lastans) modulo N)+1 and Y will be equal to ((Y1+lastans) modulo N)+1, where lastans denotes the last number that you have output, or zero if you haven't output any numbers yet.
Output
For each question query output the answer on a single line.
Constraints
- 1 ≤ N, M ≤ 100000 (105)
- 0 ≤ A, B ≤ 1000
- 0 ≤ X1, Y1 ≤ 100000 (105)
Example
Input:
5 7
1 2
2 3
3 4
4 5
c 1 4 2 3
c 2 3 5 10
q 1 3
l 1
q 1 3
l 1
q 1 3 Output:
35
0
15
Explanation
As you can see, the tree in the sample is like a line. Let's denote the first state of integers 0 0 0 0 0, where the i-th integer means the integer associated with the node i.
In the first changing query "c 1 4 2 3", the actual numbers are X = (1 + 0) modulo 5 + 1 = 2, Y = (4 + 0) modulo 5 + 1 = 5. Hence the state will be 0 2 5 8 11 after this query.
After the second changing query "c 2 3 5 10", the state will be 0 2 10 23 11 for similar reason.
In the next question query, the actual numbers are X = (1 + 0) modulo 5 + 1 = 2, Y = (3 + 0) modulo 5 + 1 = 4. Hence the answer must be 2 + 10 + 23 = 35.
In the first rollback query "l 1", the actual number is X = (1 + 35) modulo (2 + 1) = 36 modulo 3 = 0, since lastans = 36. Thus the state will be rollbacked to 0 0 0 0 0.
Then the answer of the next question query "q 1 3" must be 0, because all integers are currently 0.
In the second rollback query "l 1", the actual number is X = (1 + 0) modulo (2 + 1) = 1, since lastans = 0. Thus the state will be 0 2 5 8 11, which is the state after the firstchanging query.
Then the answer of the last question query must be 2 + 5 + 8 = 15.
题意:
一棵树,3个操作:
树上两点之间加一个等差数列,
查询树上两点之间权值和,
回到某次修改之后的状态
思路:树链剖分+主席树
#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
int root[N],lc[N*],rc[N*];
int fa[N],deep[N],bl[N],son[N],id[N],cnt;
long long k[N*],b[N*],sum[N*];
int front[N],nxt[N*],to[N*],tot;
long long A,B,QA,QB,ans;
int QL,QR;
int sum_chan,now,n,m;
int read()
{
int x=; char c=getchar();
while(c<''||c>'') c=getchar();
while(c>=''&&c<='') { x=x*+c-''; c=getchar(); }
return x;
}
struct TREE
{
long long get_sum(long long kk,long long bb,int n)
{
return (bb+bb+kk*(n-))*n/;
}
void change(int y,int &x,int l,int r)
{
x=++tot;
lc[x]=lc[y];
rc[x]=rc[y];
k[x]=k[y];
b[x]=b[y];
sum[x]=sum[y];
if(l>=QL&&r<=QR)
{
sum[x]+=get_sum(QB,(l-QL)*QB+QA,r-l+);
k[x]+=QB;
b[x]+=(l-QL)*QB+QA;
return;
}
int ll=max(QL,l),rr=min(QR,r);
sum[x]+=get_sum(QB,QA+QB*(ll-QL),rr-ll+);
int mid=l+r>>;
if(QL<=mid) change(lc[y],lc[x],l,mid);
if(QR>mid) change(rc[y],rc[x],mid+,r);
}
void query(int x,int l,int r)
{
if(!x) return;
if(QL<=l&&QR>=r)
{
ans+=sum[x];
return;
}
int ll=max(l,QL),rr=min(r,QR);
ans+=get_sum(k[x],b[x]+k[x]*(ll-l),rr-ll+);
int mid=l+r>>;
if(QL<=mid) query(lc[x],l,mid);
if(QR>mid) query(rc[x],mid+,r);
}
}Tree;
struct CHAIN
{
void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}
void dfs1(int x,int f)
{
son[x]++;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=f)
{
fa[to[i]]=x;
deep[to[i]]=deep[x]+;
dfs1(to[i],x);
son[x]+=son[to[i]];
}
}
void dfs2(int x,int top)
{
id[x]=++cnt;
bl[x]=top;
int y=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x]&&son[to[i]]>son[y]) y=to[i];
if(!y) return;
dfs2(y,top);
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x]&&to[i]!=y) dfs2(to[i],to[i]);
}
int LCA(int x,int y)
{
while(bl[x]!=bl[y])
{
if(deep[bl[x]]<deep[bl[y]]) swap(x,y);
x=fa[bl[x]];
}
if(deep[x]>deep[y]) return y;
return x;
}
void change(int x,int y,int dis)
{
int l=,r=dis;
while(bl[x]!=bl[y])
{
if(deep[bl[x]]>deep[bl[y]])
{
QL=id[bl[x]]; QR=id[x];
QA=A+(l+QR-QL)*B;
QB=-B;
Tree.change(root[sum_chan],root[sum_chan],,n);
x=fa[bl[x]];
l+=QR-QL+;
}
else
{
QL=id[bl[y]]; QR=id[y];
QA=A+(r-(QR-QL))*B;
QB=B;
Tree.change(root[sum_chan],root[sum_chan],,n);
y=fa[bl[y]];
r-=QR-QL+;
}
}
if(deep[x]<deep[y])
{
QL=id[x]; QR=id[y];
QA=A+l*B;
QB=B;
Tree.change(root[sum_chan],root[sum_chan],,n);
}
else
{
QL=id[y]; QR=id[x];
QA=A+r*B;
QB=-B;
Tree.change(root[sum_chan],root[sum_chan],,n);
}
}
void query(int x,int y)
{
while(bl[x]!=bl[y])
{
if(deep[bl[x]]<deep[bl[y]]) swap(x,y);
QL=id[bl[x]]; QR=id[x];
Tree.query(root[now],,n);
x=fa[bl[x]];
}
if(deep[x]>deep[y]) swap(x,y);
QL=id[x]; QR=id[y];
Tree.query(root[now],,n);
}
}Chain;
int main()
{
/*freopen("data.txt","r",stdin);
freopen("my.txt","w",stdout);*/
n=read(); m=read();
int u,v;
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
Chain.add(u,v);
}
Chain.dfs1(,);
Chain.dfs2(,);
tot=; char ch[]; int dis;
while(m--)
{
scanf("%s",ch);
if(ch[]=='c')
{
root[++sum_chan]=root[now];
u=read(); v=read(); A=read(); B=read();
u=(u+ans)%n+; v=(v+ans)%n+;
dis=deep[u]+deep[v]-*deep[Chain.LCA(u,v)];
Chain.change(u,v,dis);
now=sum_chan;
}
else if(ch[]=='q')
{
u=read(); v=read();
u=(u+ans)%n+; v=(v+ans)%n+;
ans=;
Chain.query(u,v);
printf("%lld\n",ans);
}
else
{
u=read();
u=(u+ans)%(sum_chan+);
now=u;
}
}
}
Codechef Observing the Tree的更多相关文章
- Codechef Union on Tree
Codechef Union on Tree https://www.codechef.com/problems/BTREE 简要题意: 给你一棵树,\(Q\)次询问,每次给出一个点集和每个点的\(r ...
- [CodeChef-QUERY]Observing the Tree
题目大意: 给你一棵树,一开始每个点的权值都是0,要求支持一下三种操作: 1.路径加等差数列. 2.路径求和. 3.回到以前的某次操作. 强制在线. 思路: 树链剖分+主席树. 最坏情况下,n个点的树 ...
- 【点分树】codechef Yet Another Tree Problem
已经连咕了好几天博客了:比较经典的题目 题目大意 给出一个 N 个点的树和$K_i$, 求每个点到其他所有点距离中第 $K_i$ 小的数值. 题目分析 做法一:点分树上$\log^3$ 首先暴力做法: ...
- Codechef Chef Cuts Tree
该思博的时候就思博到底,套路的时候不能再套路的一道题 首先我们将联通块的大小平方和进行转化,发现它就等价于连通点对数,而这个可以转化为连接两点的边数(距离)和 所以我们考虑第\(i\)天时,一个点对\ ...
- @codechef - KILLER@ Painting Tree
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 N 个点的有根树,标号 1 到 N,以 1 为根.定义 ...
- ZJOI2019Round#2
乱听课记录 关于树的分治问题&杂题选讲 张哲宇 边分治 (边分不是很鸡肋吗) 例题一 题目大意:给出两颗有正负边权的树,求出两个点\(u,v\)使得两棵树中\((u,v)\)距离的和最大. ...
- BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )
树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...
- 【启发式搜索】Codechef March Cook-Off 2018. Maximum Tree Path
有点像计蒜之道里的 京东的物流路径 题目描述 给定一棵 N 个节点的树,每个节点有一个正整数权值.记节点 i 的权值为 Ai.考虑节点 u 和 v 之间的一条简单路径,记 dist(u, v) 为其长 ...
- Codechef March Cook-Off 2018. Maximum Tree Path
目录 题意 解析 AC_code @(Codechef March Cook-Off 2018. Maximum Tree Path) 题意 给你一颗\(n(1e5)\)个点有边权有点权的树,\(Mi ...
随机推荐
- 2018-2019-20172321 《Java软件结构与数据结构》第四周学习总结
2018-2019-20172321 <Java软件结构与数据结构>第四周学习总结 教材学习内容总结 第六章 6.1列表集合 列表集合是一种概念性表示法,其思想是使事物以线性列表的方式进行 ...
- 人生苦短,我用Python!
一.程序分析 1.读取文件到缓冲区 def process_file(): # 读文件到缓冲区 try: # 打开文件 f = open("C:\\Users\\panbo\\Desktop ...
- C语言调查问卷
1.你对自己的未来有什么规划?做了哪些准备?毕业后应该不会从事编程类工作,目前有在学习感兴趣的东西.2.你认为什么是学习?学习有什么用?现在学习动力如何?为什么?学习就是把不懂变成懂,可以充实自己.没 ...
- IDEA + SSH OA 第一天(IDEA 文件夹类型了解)
回顾一下 IDEA 的文件夹的类型 设置文件夹方法 或者点击右上角的 文件夹的类型选择:可通过,右键文件夹,选择你要的类型: Sources Root : 源码的目录 Resources Root:源 ...
- lintcode-415-有效回文串
415-有效回文串 给定一个字符串,判断其是否为一个回文串.只包含字母和数字,忽略大小写. 注意事项 你是否考虑过,字符串有可能是空字符串?这是面试过程中,面试官常常会问的问题. 在这个题目中,我们将 ...
- 把握曝光三要素(上):快门、光圈、ISO
概要: 如果你还没有掌握快门.光圈和ISO,那这篇文章或许对你有所帮助! 把照片比作水池.把进光量比作水.把快门比作关闭水龙头的速度.把光圈比作水龙头的大小.把感光度ISO比作水龙头的滤网,这就变得好 ...
- workstation vmware 制作vm模板
[root@VM166136 ~]# cat copy_vmware.sh #!/bin/bash if [ $(id -u) -ne 0 ];then echo "Please use t ...
- LoadRunner录制用户操作
先说明一点,使用录制的手段拿到的测试脚本和工程师自己编写的测试脚本其实是一样的,不要觉得录制的方式low,而自己编写脚本就显得高大上,这是不对的.除非工程师本身对开发们写的代码逻辑很熟,对业务上的各个 ...
- 《Linux Shell 脚本攻略》读书笔记
本书主要讲解一些linux shell命令的用法,讲解一些shell的奇技淫巧. 第一章 小试牛刀 主要介绍一些基本shell指令 终端打印:echo.printf 别名:alias 终端处理工具:t ...
- P1054 等价表达式
题目描述 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数 ...