题目链接:BZOJ - 3531

题目分析

题目询问一条路径上的信息时,每次询问有某种特定的文化的点。

每个点的文化就相当于一种颜色,每次询问一条路径上某种颜色的点的信息。

可以使用离线算法, 类似于“郁闷的小 J ” 那道题目。将各种操作和询问按照颜色为第一关键字,时间为第二关键字排序。

那么修改颜色的操作就相当于在原颜色中是删点,在新颜色中是加点。

处理完一种颜色的操作后,要将这个颜色的点都做一次删除操作,这样,对于处理下一种颜色,树就又是空的了。

这种题,思考的时候有点晕,写代码的时候非常愉悦。

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue> using namespace std; inline void Read(int &Num)
{
char c = getchar();
bool Neg = false;
while (c < '0' || c > '9')
{
if (c == '-') Neg = true;
c = getchar();
}
Num = c - '0'; c = getchar();
while (c >= '0' && c <= '9')
{
Num = Num * 10 + c - '0';
c = getchar();
}
if (Neg) Num = -Num;
} inline int gmin(int a, int b) {return a < b ? a : b;}
inline int gmax(int a, int b) {return a > b ? a : b;} const int MaxN = 100000 + 5, MaxM = 100000 + 5, INF = 999999999; int n, m, QTop, ATot;
int W[MaxN], C[MaxN], WT[MaxN], CT[MaxN], Ans[MaxM], Father[MaxN], T[MaxN], Sum[MaxN], Max[MaxN], Son[MaxN][2]; bool isRoot[MaxN], Rev[MaxN]; struct Edge
{
int v;
Edge *Next;
} E[MaxN * 2], *P = E, *Point[MaxN]; inline void AddEdge(int x, int y)
{
++P; P -> v = y;
P -> Next = Point[x]; Point[x] = P;
} struct ES
{
int Type, Col, Pos, Num, x, y, TL, AIdx;
/*
TypeList:
1 : Change City-Pos to Num
2 : Qsum of the path(x, y)
3 : Qmax of the path(x, y)
*/
} Q[MaxN * 2 + MaxM * 2]; inline bool Cmp(ES e1, ES e2)
{
if (e1.Col != e2.Col) return e1.Col < e2.Col;
return e1.TL < e2.TL;
} queue<int> Qe; void BFS()
{
while (!Qe.empty()) Qe.pop();
Qe.push(1); Father[1] = 0;
int x;
while (!Qe.empty())
{
x = Qe.front(); Qe.pop();
for (Edge *j = Point[x]; j; j = j -> Next)
{
if (j -> v == Father[x]) continue;
Father[j -> v] = x;
Qe.push(j -> v);
}
}
} /************************ LCT Start ****************************/ inline void Update(int x)
{
Sum[x] = Sum[Son[x][0]] + Sum[Son[x][1]] + T[x];
Max[x] = gmax(T[x], gmax(Max[Son[x][0]], Max[Son[x][1]]));
} inline void Reverse(int x)
{
Rev[x] = !Rev[x];
swap(Son[x][0], Son[x][1]);
} inline void PushDown(int x)
{
if (!Rev[x]) return;
Rev[x] = false;
if (Son[x][0]) Reverse(Son[x][0]);
if (Son[x][1]) Reverse(Son[x][1]);
} inline int GetDir(int x) {return x == Son[Father[x]][0] ? 0 : 1;} void Rotate(int x)
{
int y = Father[x], f = GetDir(x) ^ 1;
PushDown(y); PushDown(x);
if (isRoot[y])
{
isRoot[y] = false;
isRoot[x] = true;
}
else Son[Father[y]][GetDir(y)] = x;
Father[x] = Father[y];
Son[y][f ^ 1] = Son[x][f];
if (Son[x][f]) Father[Son[x][f]] = y;
Son[x][f] = y; Father[y] = x;
Update(y); Update(x);
} void Splay(int x)
{
int y;
while (!isRoot[x])
{
y = Father[x];
if (isRoot[y])
{
Rotate(x);
break;
}
if (GetDir(x) == GetDir(y)) Rotate(y);
else Rotate(x);
Rotate(x);
}
} inline int Access(int x)
{
int y = 0;
while (x != 0)
{
Splay(x);
PushDown(x);
if (Son[x][1]) isRoot[Son[x][1]] = true;
Son[x][1] = y;
if (y) isRoot[y] = false;
Update(x);
y = x;
x = Father[x];
}
return y;
} inline void Make_Root(int x)
{
int t = Access(x);
Reverse(t);
} /************************ LCT End ****************************/ int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
{
Read(W[i]); Read(C[i]);
WT[i] = W[i]; CT[i] = C[i];
}
int a, b;
for (int i = 1; i <= n - 1; ++i)
{
Read(a); Read(b);
AddEdge(a, b); AddEdge(b, a);
}
char Str[5];
for (int i = 1; i <= n; ++i)
{
++QTop; Q[QTop].TL = 0; Q[QTop].Col = CT[i];
Q[QTop].Type = 1; Q[QTop].Pos = i; Q[QTop].Num = WT[i];
}
for (int i = 1; i <= m; ++i)
{
scanf("%s", Str);
Read(a); Read(b);
if (strcmp(Str, "CC") == 0)
{
++QTop; Q[QTop].TL = i; Q[QTop].Col = CT[a];
Q[QTop].Type = 1; Q[QTop].Pos = a; Q[QTop].Num = 0;
++QTop; Q[QTop].TL = i; Q[QTop].Col = b;
Q[QTop].Type = 1; Q[QTop].Pos = a; Q[QTop].Num = WT[a];
CT[a] = b;
}
else if (strcmp(Str, "CW") == 0)
{
++QTop; Q[QTop].TL = i; Q[QTop].Col = CT[a];
Q[QTop].Type = 1; Q[QTop].Pos = a; Q[QTop].Num = b;
WT[a] = b;
}
else if (strcmp(Str, "QS") == 0)
{
++QTop; Q[QTop].TL = i; Q[QTop].Col = CT[a];
Q[QTop].Type = 2; Q[QTop].x = a; Q[QTop].y = b; Q[QTop].AIdx = ++ATot;
}
else if (strcmp(Str, "QM") == 0)
{
++QTop; Q[QTop].TL = i; Q[QTop].Col = CT[a];
Q[QTop].Type = 3; Q[QTop].x = a; Q[QTop].y = b; Q[QTop].AIdx = ++ATot;
}
}
for (int i = 1; i <= n; ++i)
{
++QTop; Q[QTop].TL = INF; Q[QTop].Col = CT[i];
Q[QTop].Type = 1; Q[QTop].Pos = i; Q[QTop].Num = 0;
}
sort(Q + 1, Q + QTop + 1, Cmp);
BFS();
for (int i = 1; i <= n; ++i)
{
isRoot[i] = true; Rev[i] = false;
T[i] = 0; Max[i] = 0; Sum[i] = 0;
}
int t;
for (int i = 1; i <= QTop; ++i)
{
if (Q[i].Type == 1)
{
Splay(Q[i].Pos);
T[Q[i].Pos] = Q[i].Num;
Update(Q[i].Pos);
}
else
{
Make_Root(Q[i].x);
t = Access(Q[i].y);
if (Q[i].Type == 2) Ans[Q[i].AIdx] = Sum[t];
else Ans[Q[i].AIdx] = Max[t];
}
}
for (int i = 1; i <= ATot; ++i) printf("%d\n", Ans[i]);
return 0;
}

  

[BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】的更多相关文章

  1. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  2. bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][ ...

  3. bzoj 3531 [Sdoi2014]旅行 (树剖+线段树 动态开点)

    3531: [Sdoi2014]旅行 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 2984  Solved: 1312[Submit][Status ...

  4. BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树

    题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...

  5. [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

  6. bzoj 3531: [Sdoi2014]旅行

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. ...

  7. 【刷题】BZOJ 3531 [Sdoi2014]旅行

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...

  8. BZOJ 3531 SDOI2014 旅行 树链剖分+线段树动态开点

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531 题意概述: 给出一棵N个点的树,树上的每个结点有一个颜色和权值,支持以下四种操作: ...

  9. BZOJ 3531: [Sdoi2014]旅行 权值线段树 + 树链剖分

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...

随机推荐

  1. android自定义View之NotePad出鞘记

    现在我们的手机上基本都会有一个记事本,用起来倒也还算方便,记事本这种东东,如果我想要自己实现,该怎么做呢?今天我们就通过自定义View的方式来自定义一个记事本.OK,废话不多说,先来看看效果图. 整个 ...

  2. R-大数据分析挖掘(2-R爬虫)

    RCurl作者:

  3. Android的Manifest配置文件介绍

    一.关于AndroidManifest.xml       AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了package中暴露的组件(ac ...

  4. java编写一个端口扫描器

    好久没写java了,学的时候,也没学习网络编程这一块,无意中看到了一本书,于是小小复习一下java,写个端口扫描器,玩玩吧,网上这种小公具有的是,就是自己无聊写着玩玩. 源代码如下: 共两个类,比较简 ...

  5. 对bigDecimal的一些探索

    一般直接用简单的double等来做浮点计算可能会因为计算机的浮点运算机制出现一点问题,不符合生活中的计算常识,于是java就给我们包装了大数据类,bigdecimal用于处理浮点数据类.当然也有处理整 ...

  6. A题笔记(11)

    No.1508  代码:https://code.csdn.net/snippets/192058 考察点:①char型字符转换成对应的 ASKII 的编码 可以通过这样对 string 的每一个字符 ...

  7. ios PullToRefresh using animated GIF or image array or Vector image

    说说那些令人惊叹的下拉效果 1. 动画下拉,这里借用一下github的资源 优点:直接用gif图处理,下拉进度完全按照gif图运行时间,只要时间和下拉进度匹配就可以了, 效果很流畅 https://d ...

  8. 安装flash 插件scaleform出现错误:Scaleform Launch Panel.Launcher.handleDataLoaderIOError(): Loading XML Failedscaleform

    经排查发现是Scaleform Launcher.swf报的错 (C:\Users\Administrator\AppData\Local\Adobe\Flash CC\zh_CN\Configura ...

  9. ImageIcon图像处理相关测试【一些特殊的处理方式】

    /*************以下源码通过测试******************************/ package cn.jason.ios.images; import java.awt.F ...

  10. c++ primer复习(二)

    1 悬垂else来自于else语句搭配的if语句的二义性 2 理解switch代码: switch(c) { case 'a': a++; case 'b': b++; default: x++; } ...