luogu P4115 Qtree4
题目链接
题解
动态点分治,和上一题一样.同样三个堆.就是带权,用边权替换深度就好
为什么要单独写这个题解呢,因为我卡常卡了一天....据说树剖比rmq快? 在第24次AC
同样也有更有做法
代码
#include<queue>
#include<cstdio>
#include<cctype>
#include<algorithm>
/*char ch;
char buf[100000],*p1 = buf,*p2 = buf;
int F = 1;
#define nc() \
p1 == p2 && (p2 = (p1 = buf) + fread(buf,1,100000,stdin),p1 == p2) ? EOF :*p1 ++;
#define read(x) \
x = 0;ch = nc();F = 1; \
while(!isdigit(ch)) { if (ch == '-') F = -1; ch = nc();}\
while(isdigit(ch))x = x*10+ch - '0',ch = nc();\
x *= F;
*/
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int MAXIN=3e5;
char IN[MAXIN],*SS=IN,*TT=IN;
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
inline int read() {
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
#define INF 998244353
const int maxn = 100007;
int son[maxn],f[maxn],mn[maxn << 1][25],root,tot;
struct node {
int u,v,next,w;
} edge[maxn << 1];
int head[maxn],num = 0;
inline void add_edge(int u,int v,int w) {
edge[++ num].v = v;edge[num].next = head[u];head[u] = num;
edge[num].w = w;
}
int n;
int lg[maxn << 1],dfn;// = 0;
bool col[maxn];
struct Heap {
std::priority_queue<int>A,B;
inline void push(int x) { A.push(x); }
inline void erase(int x) { B.push(x); }
inline void pop() { while(B.size() && A.top() == B.top()) A.pop(),B.pop(); A.pop(); }
inline int top() {
while(B.size() && A.top() == B.top()) A.pop(),B.pop();
return A.top();
}
inline int size() { return A.size() - B.size(); }
int retop() { if(size() < 2) return 0;int x = top();pop();int ret = top();push(x);return ret;}
} b[maxn],c[maxn],ans;
inline void insert(Heap &s) {if(s.size() > 1)ans.push(s.top() + s.retop());}
inline void dele(Heap &s) {if(s.size() > 1) ans.erase(s.top() + s.retop());}
int pos[maxn],Dis[maxn];
int id[maxn],tm;
void dfs_rmq (int x,int fa) {
int t = ++ tm; mn[pos[x] = ++ dfn][0] = tm,id[t] = x;
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v == fa)continue;
Dis[v] = Dis[x] + edge[i].w;
dfs_rmq(v,x);
mn[++ dfn][0] = t; //访问完子树后加上Qwq
}
}
inline int lca(int x,int y) {
x = pos[x];y = pos[y];
if(y < x) std::swap(x,y);
int k = lg[y - x + 1];
return id[std::min(mn[x][k],mn[y - (1 << k) + 1][k])];
}
inline int dis(int x,int y) {
return Dis[x] + Dis[y] - 2 * Dis[lca(x,y)];
}
bool vis[maxn];int fa[maxn];
void get_root(int x,int fa) {
son[x] = 1; f[x] = 0;
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v == fa || vis[v]) continue;
get_root(v,x);
son[x] += son[v];f[x] = std::max(f[x],son[v]);
}
f[x] = std::max(f[x],tot - son[x]);
if(f[x] < f[root]) root = x;
}
void get(int x,int Fa,int rt) {
b[root].push(dis(x,fa[root]));
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v; if(v == Fa || vis[v]) continue;
get(v,x,rt);
}
}
void build(int x,int Fa) {
fa[x] = Fa;vis[x] = 1;
c[x].push(0);
get(x,0,Fa);
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(!vis[v] && v != Fa) {
tot = son[edge[i].v];root = 0;f[0] = INF;
get_root(edge[i].v,x);
v = root;
build(root,x);
c[x].push(b[v].top());
}
}
insert(c[x]);
}
void turn(int x,bool type) {
dele(c[x]);
if(type) c[x].erase(0);
else c[x].push(0);
insert(c[x]);
for(int i = x;i;i = fa[i]) {
dele(c[fa[i]]);
//printf("%d ",i);
if(b[i].size()) c[fa[i]].erase(b[i].top());
if(type)b[i].erase(dis(x,fa[i])); else b[i].push(dis(x,fa[i]));
if(b[i].size()) c[fa[i]].push(b[i].top());
insert(c[fa[i]]);
}
//puts("");
}
inline char get(){
char c=gc();
while(c!='A'&&c!='C') c=gc();
return c;
}
int main() {
n = read();
//read(n);
for(int u,v,w,i = 1;i < n;++ i) {
u = read(),v = read(),w = read();
//read(u);read(v);read(w);
add_edge(u,v,w);add_edge(v,u,w);
}
dfs_rmq(1,0);
for(int i = 2;i <= dfn;++ i) lg[i] = lg[i >> 1] + 1;
for(int i = 1;i <= lg[dfn];++ i)
for(int j = dfn - (1 << i - 1);j;-- j)
mn[j][i] = std::min(mn[j][i - 1],mn[j + (1 << i - 1)][i - 1]);
f[0] = INF; root = 0; tot = n;
get_root(1,0);
build(root,0);
//char opt[10];
int Q = read();
int sum = n;
for(int asd;Q --;) {
//scanf("%s",opt + 1);
if(get() == 'C') {
asd = read();//read(asd);
if(col[asd]) turn(asd,0), sum ++,col[asd] = 0;
else turn(asd,1),sum --,col[asd] = 1;
}
else {
if(sum == 1)puts("0");
else if(!sum)puts("They have disappeared.");
else printf("%d\n",std::max(0,ans.top()));
}
}
return 0;
}
luogu P4115 Qtree4的更多相关文章
- 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV
意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...
- 洛谷 4115 Qtree4——链分治
题目:https://www.luogu.org/problemnew/show/P4115 论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb ...
- Luogu 魔法学院杯-第二弹(萌新的第一法blog)
虽然有点久远 还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题 沉迷游戏,伤感情 #include <queue> ...
- luogu p1268 树的重量——构造,真正考验编程能力
题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...
- [luogu P2170] 选学霸(并查集+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...
- [luogu P2647] 最大收益(贪心+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,--,n.你可以在这当中任意选择任意多个物品. ...
- Luogu 考前模拟Round. 1
A.情书 题目:http://www.luogu.org/problem/show?pid=2264 赛中:sb题,直接暴力匹配就行了,注意一下读入和最后一句话的分句 赛后:卧槽 怎么只有40 B.小 ...
- luogu P2580 于是他错误的点名开始了
luogu P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...
- CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)
CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...
随机推荐
- Amcharts 柱状图和线形图
最近需要学习 Amcharts ,他的图表功能确实很强大.但是网上搜索到的教程很少,开始学起的确有点不方便.于是我决定把我学习的觉得好的途径,放到博客上. 下面的代码可以直接复制,但是文件要从官网上下 ...
- html5手机Web单页应用实践--起点移动阅读
一开始以hybrid形式做了一个android的小说阅读客户端,叫4G阅读.而后由于业务需求,要迅速实现纯手机html5 版的,所以就直接在原先客户端内内嵌的网页进行改版,快速实现以后在优化的过程中发 ...
- js-打地鼠游戏开发
[生成画布] 第1课[随机生成地鼠] 第2课[定时生成地鼠] 第3课[打地鼠完结篇] 第4课 优酷在线播放地址 http://list.youku.com/albumlist/show?id=2939 ...
- MYSQL三种安装方式--二进制包安装
1. 把二进制包下载到/usr/local/src下 2. 如果是tar.gz包,则使用tar zxvf 进行解压 如果是tar包,则可以使用tar xvf 进行解压 3. $ mv mysql-5. ...
- C++ 和Java继承机制的比较
摘要: C++支持类的多继承,而Java采用类的单继承.C++中的继承成分只有类(模板属于带参数的类,结构和联合是特殊的类),Java中除了类还有接口的继承,而且允许接口的多继承,可以间接地实现类多继 ...
- svm和svr区别--摘自其它博客
学习笔记:SVM柔性边界的补充和SVR(支持向量回归) 作者 小刺猬yyx 关注 2016.08.06 10:31* 字数 1608 阅读 421评论 0喜欢 2 上一个笔记对于SVM不能完美分类的情 ...
- socket编程——sockaddr_in结构体操作
sockaddr结构体 sockaddr的缺陷: struct sockaddr 是一个通用地址结构,这是为了统一地址结构的表示方法,统一接口函数,使不同的地址结构可以被bind() , connec ...
- C/C++面试题目一
C/C++开发工程师面试题目(一)(附答案分析) 推荐:自己根据在面试中碰到做过的一些题目以及总结的题目,希望对面试的同学有所帮助. 一. 选择题 1. 下列类中( )不是输入输出流类iostrea ...
- 教你如何更改android应用的包名
Android 源码自带了很多应用程序,想改个包名方便修改?很简单,两步搞定,以packages/apps/Settings为例: 1.打开AndroidManifest.xml,把 <mani ...
- Spring学习-理解IOC和依赖注入
最近刚买了一本介绍ssm框架的书,里面主要对Mybatis.spring.springmvc和redis做了很多的讲解,个人觉得虽然有的内容我看不懂,但是整体上还是不错的.最近正在学习中,一边学习一边 ...