树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, 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树上询问( 可持久化线段树 + 树链剖分 )的更多相关文章

  1. [BZOJ 3221][Codechef FEB13] Obserbing the tree树上询问

    [BZOJ 3221]Obserbing the tree树上询问 题目 小N最近在做关于树的题.今天她想了这样一道题,给定一棵N个节点的树,节点按1~N编号,一开始每个节点上的权值都是0,接下来有M ...

  2. bzoj 3221: Obserbing the tree树上询问 树链剖分+线段树

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3221 题解 啊呀...这是昨天的考试题啊...直接就粘了.. 与4515: [Sdoi2 ...

  3. Codechef TSUM2 Sum on Tree 点分治、李超线段树

    传送门 点分治模板题都不会迟早要完 发现这道题需要统计所有路径的信息,考虑点分治统计路径信息. 点分治之后,因为路径是有向的,所以对于每一条路径都有向上和向下的两种.那么如果一条向上的路径,点数为\( ...

  4. spoj COT - Count on a tree (树上第K小 LCA+主席树)

    链接: https://www.spoj.com/problems/COT/en/ 思路: 首先看到求两点之前的第k小很容易想到用主席树去写,但是主席树处理的是线性结构,而这道题要求的是树形结构,我们 ...

  5. 计蒜客 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 ...

  6. BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)

    题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...

  7. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  8. 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 ...

  9. [BZOJ 4771]七彩树(可持久化线段树+树上差分)

    [BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...

随机推荐

  1. C# 用模板生成静态页

    最近在研究静态页输出的问题,找了一些资料.做了一个简单的模板模式的静态输出 模板代码: <html xmlns="http://www.w3.org/1999/xhtml"& ...

  2. js判断的执行顺序

    js预编译是对每一个<script>标签片段进行的.预编译声明所有var变量(初始为undefined),解析定义式函数语句. 还有个关于 "window作用域下,a = 1和v ...

  3. jQuery基础---Ajax基础教程

    jQuery基础---Ajax基础 内容提纲: 1.Ajax 概述 2.load()方法 3.$.get()和$.post() 4.$.getScript()和$.getJSON() 5.$.ajax ...

  4. mysql中select distinct的用法

    在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但 往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...

  5. 数组转DataTable

    using System; using System.Data; namespace ArrayToDataTable { class ArrayToDataTable { /// <summa ...

  6. JavaScript基本概念(操作符)

    一元操作符 一元操作符在处理所有的非数值时,相当于将该值经过Number()转换成数值,如 +"12" 将把 "12" 字符串转换为数字. 位操作符 负数在计算 ...

  7. Hibernate摘记

    原理: 1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件2.由hibernate.cfg.xml中的<mapping reso ...

  8. [问题解决] LaTex Error:Unknown graphics extension:.eps

    错误:编译的时候显示:“!LaTex Error:Unknown graphics extension:.eps” 发生场景:Latex写论文 解决方案: latex eps.texdvi2ps ep ...

  9. perl 公交车查询

    <pre name="code" class="cpp">decode_json 必须是unicode形式的字符,Dump不支持显示unicode形 ...

  10. layout_weight 的解释及使用

    layout_weight 的解释及使用 转自:http://my.oschina.net/jsan/blog/191492 在Android的控件布局中,有一个奇葩的 layout_weight 属 ...