树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, 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. 【STL】算法 — partial_sort

    partial_sort接受一个middle迭代器,使序列中的middle-first个最小元素以递增顺序排序.置于[first, middle)内.以下是測试代码: #include <ios ...

  2. 【MFC学习笔记-作业9-基于单击响应的计算平均成绩】【】

    要求..单击出现 一个输入成绩的框,点确定后,计算平均成绩 意义很大~ 完成对话框   再写个鼠标点击的响应部分 鼠标点击的响应部分为难点.... void CWj1401_0302140107_9V ...

  3. Oracle存储过程 使用游标、数组的配合查询

    查询输入的门牌号码是否在标准门牌库中存在.存在则返回相应的号码. public string GetValidate(){ OracleConnection conn = ConnectOra(); ...

  4. 读书笔记一 Java程序员的基本修养(数组及其内存管理)

    1.1 数组初始化 1.1.1 java数组是静态的 java数组被初始化之后,该数组所占的内存空间.数组长度都是不可变的. java程序中的数组必须经过初始化才可使用. 数组的初始化有两种方式: 1 ...

  5. UVa 202 - Repeating Decimals

    给你两个数,问你他们相除是多少,有无限循环就把循环体括号括起来 模拟除法运算 把每一次的被除数记下,当有被除数相同时第一个循环就在他们之间. 要注意50个数之后要省略号...每一次输出之后多打一个回车 ...

  6. 图的最短路径问题————树上奶牛(tree.cpp)

    和往常一样,继续从题目引入 树上奶牛 (tree.cpp) [题目描述] 农夫John的奶牛不是住在地上而是住在树上的QWQ. 奶牛之间需要串门,不过在串门之前他们会向John询问距离的大小.可是Jo ...

  7. Qt5 多显示器获取不同显示器的分辨率和位置的方法

    Qt5 多显示器获取不同显示器的分辨率和位置的方法 先放官方文档链接:QDesktopWidget - Qt5 Reference 之前一直在用被我乱搞后的ShadowPlayer作为默认播放器,后来 ...

  8. shell ps1 提示设置

    PS1="\[\033[01;37m\]\u\[\033[00m\]@\[\033[01;31m\]localhost \t\[\033[00m\]:\[\033[01;35m\]\w\[\ ...

  9. Lucene学习之初步了解

    全文搜索 比如,我们一个文件夹中,或者一个磁盘中有很多的文件,记事本.world.Excel.pdf,我们想根据其中的关键词搜索包含的文件.例如,我们输入Lucene,所有内容含有Lucene的文件就 ...

  10. contact表单错误解决记录

    在上篇表单验证中,过程中可谓坎坷,记录一下错误问题及解决方案. 我们用到的模板contact_form.html如下,其他urls.py自行去修改. <html> <head> ...