
树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法:码码码码码码码码...码完就AC啦. O(M log N)
-------------------------------------------------------------------
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 100009;
int N, Q, Top, L, R, dfn, T;
int Id[maxn], sz[maxn], dep[maxn], fa[maxn], ch[maxn], top[maxn];
inline int getint() {
char c = getchar();
for(; !isdigit(c); c = getchar());
int ret = 0;
for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
return ret;
}
inline ll getll() {
char c = getchar();
for(; !isdigit(c); c = getchar());
ll ret = 0;
for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
return ret;
}
struct edge {
int t;
edge* n;
} E[maxn << 1], *Pt = E, *H[maxn];
inline void AddEdge(int u, int v) {
Pt->t = v, Pt->n = H[u], H[u] = Pt++;
}
void dfs(int x) {
sz[x] = 1, ch[x] = -1;
for(edge* e = H[x]; e; e = e->n) if(e->t != fa[x]) {
dep[e->t] = dep[x] + 1;
fa[e->t] = x;
dfs(e->t);
sz[x] += sz[e->t];
if(!~ch[x] || sz[ch[x]] < sz[e->t]) ch[x] = e->t;
}
}
void DFS(int x) {
top[x] = Top;
Id[x] = ++dfn;
if(~ch[x]) DFS(ch[x]);
for(edge* e = H[x]; e; e = e->n)
if(e->t != fa[x] && e->t != ch[x]) DFS(Top = e->t);
}
void Init() {
N = getint(), Q =getint();
for(int i = 1; i < N; i++) {
int u = getint() - 1, v = getint() - 1;
AddEdge(u, v), AddEdge(v, u);
}
fa[0] = -1, dep[0] = 0, dfs(0);
DFS(dfn = Top = 0);
}
struct Mark {
ll f, d;
Mark() : f(0), d(0) {
}
Mark(ll _f, ll _d) : f(_f), d(_d) {
}
Mark operator += (const Mark o) {
f += o.f, d += o.d;
return *this;
}
Mark Rev(int len) {
return Mark(f + (len - 1) * d, -d);
}
Mark Cut(int len) {
return Mark(f + len * d, d);
}
inline ll Sum(int len, int s = 0) {
return ll(len) * (f + d * s) + (d * len * (len - 1) >> 1);
}
};
struct Node {
Node *lc, *rc;
ll sm;
Mark t;
inline void upd(int len) {
if(len > 1) {
sm = lc->sm + rc->sm;
} else
sm = 0;
sm += t.Sum(len);
}
} pool[20000009], *pt, *Root[maxn];
void Init_sgt() {
pt = pool;
pt->lc = pt->rc = pt;
pt->t = Mark();
Root[0] = pt++;
}
int LCA(int u, int v) {
for(; top[u] != top[v]; u = fa[top[u]])
if(dep[top[u]] < dep[top[v]]) swap(u, v);
return dep[u] < dep[v] ? u : v;
}
Node* Modify(Node* t, int l, int r, Mark mk) {
Node* o = pt++;
o->t = t->t;
o->lc = t->lc, o->rc = t->rc;
if(L <= l && r <= R) {
o->t += mk;
} else {
int m = (l + r) >> 1;
if(L <= m) o->lc = Modify(o->lc, l, m, mk);
if(m < R) o->rc = Modify(o->rc, m + 1, r, L <= m ? mk.Cut(m - max(L, l) + 1) : mk);
}
o->upd(r - l + 1);
return o;
}
Node* MODIFY(Node* p, int u, int v, Mark t) {
int lca = LCA(u, v);
for(; top[u] != top[v]; u =fa[top[u]]) {
if(dep[top[u]] < dep[top[v]]) {
t = t.Rev(dep[u] + dep[v] - (dep[lca] << 1) + 1);
swap(u, v);
}
L = Id[top[u]], R = Id[u];
p = Modify(p, 1, N, t.Rev(dep[u] - dep[top[u]] + 1));
t = t.Cut(dep[u] - dep[top[u]] + 1);
}
if(dep[u] > dep[v]) {
t = t.Rev(dep[u] - dep[v] + 1);
swap(u, v);
}
L = Id[u], R = Id[v];
p = Modify(p, 1, N, t);
return p;
}
void Query(Node* t, int l, int r, Mark o, ll &ret) {
if(L <= l && r <= R) {
ret += t->sm + o.Sum(r - l + 1);
} else {
int m = (l + r) >> 1;
o += t->t;
if(L <= m) Query(t->lc, l, m, o, ret);
if(m < R) Query(t->rc, m + 1, r, o.Cut(m + 1 - l), ret);
}
}
ll QUERY(Node* t, int u, int v) {
ll ret = 0;
for(; top[u] != top[v]; u = fa[top[u]]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
L = Id[top[u]], R = Id[u];
Query(t, 1, N, Mark(), ret);
}
if(dep[u] > dep[v]) swap(u, v);
L = Id[u], R = Id[v];
Query(t, 1, N, Mark(), ret);
return ret;
}
void Work() {
char c;
int t = 0;
ll ans = 0;
Init_sgt();
Node* Rt = Root[0];
while(Q--) {
scanf(" %c", &c);
if(c == 'c') {
int u = getll() ^ ans, v = getll() ^ ans;
ll f = getll(), d =getll();
Rt = Root[++t] = MODIFY(Rt, u - 1, v - 1, Mark(f, d));
} else if(c == 'q') {
printf("%lld\n", ans = QUERY(Rt, (getll() ^ ans) - 1, (getll() ^ ans) - 1));
} else
Rt = Root[getll() ^ ans];
}
}
int main() {
Init();
Work();
return 0;
}
-------------------------------------------------------------------
3221: [Codechef FEB13] Obserbing the tree树上询问
Time Limit: 20 Sec Memory Limit: 1280 MB
Submit: 295 Solved: 55
[Submit][Status][Discuss]
Description
小N最近在做关于树的题。今天她想了这样一道题,给定一棵N个节点的树,节点按1~N编号,一开始每个节点上的权值都是0,接下来有M个操作。第一种操作是修改,给出4个整数X,Y,A,B,对于X到Y路径上加上一个首项是A,公差是B的等差数列,因为小N十分谨慎,所以她每做完一个修改操作就会保存一次,初始状态是第0次保存的局面。第二种操作是求和,给出2个整数X,Y,输出X到Y路径上所有节点的权值和。第三种操作是读取之前第X次保存的局面,所有节点的状态回到之前第X次保存的状态。现在请你对每一个求和操作输出答案。
Input
第一行2个整数N,M表示节点个数和操作次数。
接下来N-1行每行2个整数Ui,Vi表示了这棵树中Ui和Vi这2个节点间有边相连。
接下来M行每行先有一个字符表示了操作的类型:
如果是’c’,那么代表了一个修改操作,接下来有4个整数X1,Y1,A,B,为了使得询问在线,正确的X=X1 xor上次输出的数,Y=Y1 xor上次输出的数,如果之前没有输出过那么当成0。
如果是’q’,那么代表了一个求和操作,接下来有2个整数X1,Y1,和修改操作一样需要xor上次输出。
如果是’l’,那么代表了一次读取操作,接下来1个整数X1,正确的X=X1 xor上次输出的数。
Output
Sample Input
5 7
1 2
2 3
3 4
4 5
c 2 5 2 3
c 3 4 5 10
q 1 3
l 13
q 13 15
l 6
q 6 4
Sample Output
12
7
7
HINT
100%的数据中N,M<=100000,0<=A,B<=1000,0<=X1,Y1<=10^1,修改次数<M/2,不会读取没保存的局面
Source
- [BZOJ 3221][Codechef FEB13] Obserbing the tree树上询问
[BZOJ 3221]Obserbing the tree树上询问 题目 小N最近在做关于树的题.今天她想了这样一道题,给定一棵N个节点的树,节点按1~N编号,一开始每个节点上的权值都是0,接下来有M ...
- bzoj 3221: Obserbing the tree树上询问 树链剖分+线段树
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3221 题解 啊呀...这是昨天的考试题啊...直接就粘了.. 与4515: [Sdoi2 ...
- Codechef TSUM2 Sum on Tree 点分治、李超线段树
传送门 点分治模板题都不会迟早要完 发现这道题需要统计所有路径的信息,考虑点分治统计路径信息. 点分治之后,因为路径是有向的,所以对于每一条路径都有向上和向下的两种.那么如果一条向上的路径,点数为\( ...
- spoj COT - Count on a tree (树上第K小 LCA+主席树)
链接: https://www.spoj.com/problems/COT/en/ 思路: 首先看到求两点之前的第k小很容易想到用主席树去写,但是主席树处理的是线性结构,而这道题要求的是树形结构,我们 ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)
题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 9280 Solved: 2421 ...
- [BZOJ 4771]七彩树(可持久化线段树+树上差分)
[BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...
随机推荐
- 第十一届GPCT杯大学生程序设计大赛完美闭幕
刚刚过去的周六(6月7号)是今年高考的第一天,同一时候也是GPCT杯大学生程序设计大赛颁奖的日子,以下我们用图文再回想一下本次大赛颁奖的过程. 评审过程的一些花絮<感谢各位评审这些天的付出!&g ...
- MVC3学习随记一
最近才接触mvc,也是才接触linq语法,还有EntiyFramework,个人感觉这种开发模式还是挺不错的,随手记点笔记,简单做个增删改查吧 一.实例化上下文ObjectContext: 引用空间那 ...
- struts 2 debug标签隐藏不显示
struts2 的标签debug在页面中应用,并且struts的配置文件中也设置为开发模式,但是这个标签却被隐藏了,究其原因,是因为页面中body元素生命了class,其样式覆盖了原来的样式. 比如: ...
- Hibernate中load与get的区别
1.get()采用立即加载方式,而load()采用延迟加载; ①get()方法执行的时候,会立即向数据库发出查询语句;(查询顺序:内部缓存,数据库) ②load()方法返回的是一个代理(此代理中只有一 ...
- Linux 安装Nginx详细图解教程
进入:/usr/java/nginx位置 下载nginx: wget http://nginx.org/download/nginx-1.8.0.tar.gz 下载openssl : wget htt ...
- c++多线程参数的传递
#include <iostream> #include <pthread.h> //多线程相关操作头文件,可移植众多平台 using namespace std; struc ...
- javac编译原理(一)
我们都知道,计算机只能识别二进制语言,是不能直接识别java c c++等高级语言的.将高级语言转化成计算机可以是别的二进制语言,这个过程就叫编译. 有次面试,面试官问了一道“java的编译原理是什么 ...
- View的事件分发机制
一.点击事件的传递规则 传递事件的主要方法: public boolean dispatchTouchEvent(MotionEvent ev) 如果事件能够传递到当前View,则该方法一定会被调用. ...
- Python之路第三天,基础(3)-set,函数,内置函数,文件,三元运算,lambda
set集合 集合是一个无序的,不重复的元素集合. 集合的创建: name_set = {'tom','jerry','alex','rose'} 或 name_set = set(['tom','je ...
- Robot Framework语法学习(一)
Robot Framework语法学习: 一.变量的声明.赋值与使用 1.变量标识符:每个变量都可以用 变量标识符 ${变量名} 来表示. 2.变量声明:可以在TestSuite上点右键或者在Edi ...