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 ...
随机推荐
- HDU 5464 Clarke and problem 动态规划
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5464 Clarke and problem Accepts: 130 Submissions: ...
- 关于初装kali linux 2.0时DEB文件安装失败的问题
kali linux 是一个基于debian 的linux发行版本,支持deb文件格式的图形化安装. 刚装上kali linux时安装程序总是失败,提示处理时错误. 经过一番爬贴,是软件源的原因,解决 ...
- 安恒杯-babysql
1. 库名 ?id= and extractvalue(,(select group_concat(0x3a,schema_name) from information_schema.schemata ...
- opencv 矩阵类数据的运算
参考:http://blog.sina.com.cn/s/blog_7908e1290101i97z.htmlhttp://blog.sina.com.cn/s/blog_afe2af380101bq ...
- libnl3.2.25安装编译
1,tar zxvf libnl-3.2.25.tar.gz 2,cd libnl-3.2.25 3,./configure --prefix=/usr --sysconfdir=/etc --d ...
- 采用FPGA实现UART转SPI
应用笔记 V1.1 2015/2/10 采用FPGA实现UART转SPI 概述 本文提供了实现UART转SPI的Verilog代码的功能描述.这份笔记将介绍UART和SPI的基本知识,代码设计 ...
- 如何在VScode中添加代码片段
拿 VUE 举例,新建 VUE 文件,输入前缀,出现代码段 文件 ---> 首选项 ---> 用户代码片段 在输入框中输入 vue ,找到 vue.json ,然后在 vue.json ...
- java实现PV操作
package com.jayfulmath.designpattern.command; import java.util.concurrent.Semaphore; /* P(S): ①将信号量S ...
- OEM SLP Key
OEM SLP Key Windows Server 2012 R2 Datacenter ===================== 2N9T6-Y284D-T68G9-QGV6X-FRFTD -- ...
- Ulipad和有道词典冲突解决方法
问题现象 Ulipad和目前版本的有道词典有冲突,表现为先开有道词典,Ulipad就无法运行. 解决方法 找到Ulipad安装目录下的config.ini,添加以下两行: [server] port= ...
