【SDOI 2014】 旅行
【题目链接】
【算法】
树链剖分
每个宗教建一棵线段树,注意数据量大,要动态开点
【代码】
#include<bits/stdc++.h>
using namespace std;
#define MAXLOG 18
const int MAXN = 1e5 + ;
const int MAXS = 1e7 + ; int i,n,q,x,y,t,Lca,SZ,timer;
int w[MAXN],c[MAXN],son[MAXN],dfn[MAXN],top[MAXN],size[MAXN],anc[MAXN][MAXLOG],
dep[MAXN],fa[MAXN],lc[MAXS],rc[MAXS],sum[MAXS],Max[MAXS],root[MAXN];
vector<int> e[MAXN];
char opt[]; inline void dfs1(int x)
{
int i,y;
anc[x][] = fa[x];
for (i = ; i < MAXLOG; i++)
{
if (dep[x] < ( << i)) break;
anc[x][i] = anc[anc[x][i-]][i-];
}
size[x] = ;
for (i = ; i < e[x].size(); i++)
{
y = e[x][i];
if (fa[x] != y)
{
dep[y] = dep[x] + ;
fa[y] = x;
dfs1(y);
size[x] += size[y];
if (size[y] > size[son[x]]) son[x] = y;
}
}
}
inline void dfs2(int x,int tp)
{
int i,y;
dfn[x] = ++timer;
top[x] = tp;
if (son[x]) dfs2(son[x],tp);
for (i = ; i < e[x].size(); i++)
{
y = e[x][i];
if (fa[x] != y && son[x] != y) dfs2(y,y);
}
}
inline int lca(int x,int y)
{
int i,t;
if (dep[x] > dep[y]) swap(x,y);
t = dep[y] - dep[x];
for (i = ; i < MAXLOG; i++)
{
if (t & ( << i))
y = anc[y][i];
}
if (x == y) return x;
for (i = MAXLOG - ; i >= ; i--)
{
if (anc[x][i] != anc[y][i])
{
x = anc[x][i];
y = anc[y][i];
}
}
return fa[x];
}
inline void push_up(int root)
{
Max[root] = max(Max[lc[root]],Max[rc[root]]);
sum[root] = sum[lc[root]] + sum[rc[root]];
}
inline void modify(int &root,int l,int r,int x,int val)
{
int mid;
if (!root) root = ++SZ;
if (l == r)
{
Max[root] = sum[root] = val;
return;
}
mid = (l + r) >> ;
if (mid >= x) modify(lc[root],l,mid,x,val);
else modify(rc[root],mid+,r,x,val);
push_up(root);
}
inline int query_max(int root,int l,int r,int ql,int qr)
{
int mid;
if (!root) return ;
if (l == ql && r == qr) return Max[root];
mid = (l + r) >> ;
if (mid >= qr) return query_max(lc[root],l,mid,ql,qr);
else if (mid + <= ql) return query_max(rc[root],mid+,r,ql,qr);
else return max(query_max(lc[root],l,mid,ql,mid),query_max(rc[root],mid+,r,mid+,qr));
}
inline int query_sum(int root,int l,int r,int ql,int qr)
{
int mid;
if (!root) return ;
if (l == ql && r == qr) return sum[root];
mid = (l + r) >> ;
if (mid >= qr) return query_sum(lc[root],l,mid,ql,qr);
else if (mid + <= ql) return query_sum(rc[root],mid+,r,ql,qr);
else return query_sum(lc[root],l,mid,ql,mid) + query_sum(rc[root],mid+,r,mid+,qr);
} inline int solve1(int c,int x,int y)
{
int ans = ,
tx = top[x],ty = top[y];
while (tx != ty)
{
ans = max(ans,query_max(root[c],,n,dfn[tx],dfn[x]));
x = fa[tx]; tx = top[x];
}
ans = max(ans,query_max(root[c],,n,dfn[y],dfn[x]));
return ans;
}
inline int solve2(int c,int x,int y)
{
int ans = ,
tx = top[x],ty = top[y];
while (tx != ty)
{
ans += query_sum(root[c],,n,dfn[tx],dfn[x]);
x = fa[tx]; tx = top[x];
}
ans += query_sum(root[c],,n,dfn[y],dfn[x]);
return ans;
} int main()
{ scanf("%d%d",&n,&q);
for (i = ; i <= n; i++) scanf("%d%d",&w[i],&c[i]);
for (i = ; i < n; i++)
{
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
dfs1();
dfs2(,);
for (i = ; i <= n; i++) modify(root[c[i]],,n,dfn[i],w[i]);
while (q--)
{
scanf("%s",&opt);
if (strcmp(opt,"CC") == )
{
scanf("%d%d",&x,&y);
modify(root[c[x]],,n,dfn[x],);
c[x] = y;
modify(root[c[x]],,n,dfn[x],w[x]);
}
if (strcmp(opt,"CW") == )
{
scanf("%d%d",&x,&y);
modify(root[c[x]],,n,dfn[x],y);
w[x] = y;
}
if (strcmp(opt,"QS") == )
{
scanf("%d%d",&x,&y);
Lca = lca(x,y);
t = solve2(c[x],x,Lca) + solve2(c[x],y,Lca);
if (c[Lca] == c[x]) t -= w[Lca];
printf("%d\n",t);
}
if (strcmp(opt,"QM") == )
{
scanf("%d%d",&x,&y);
Lca = lca(x,y);
printf("%d\n",max(solve1(c[x],x,Lca),solve1(c[x],y,Lca)));
}
} return ; }
【SDOI 2014】 旅行的更多相关文章
- 【BZOJ 3531】【SDOI 2014】旅行
因为有$10^5$个宗教,需要开$10^5$个线段树. 平时开的线段树是“满”二叉树,但在这个题中代表一个宗教的线段树管辖的区间有很多点都不属于这个宗教,也就不用“把枝叶伸到这个点上”,所以这样用类似 ...
- 【BZOJ 3529】【SDOI 2014】数表
看Yveh的题解,这道题卡了好长时间,一直不明白为什么要······算了当时太naive我现在都不好意思说了 #include<cstdio> #include<cstring> ...
- [BZOJ 3530][Sdoi 2014]数数
阿拉~好像最近总是做到 AC 自动机的题目呢喵~ 题目的算法似乎马上就能猜到的样子…… AC 自动机 + 数位 dp 先暴力转移出 f[i][j] :表示从 AC 自动机上第 j 号节点走 i 步且不 ...
- BZOJ 3533 sdoi 2014 向量集
设(x,y)为Q的查询点,分类讨论如下:1.y>0: 最大化a*x+b*y,维护一个上凸壳三分即可 2.y<0:最大化a*x+b*y 维护一个下凸壳三分即可 我们考虑对时间建出一棵线段 ...
- [SDOI 2014]数表
Description 有一张N×m的数表,其第i行第j列(1 < =i < =N,1 < =j < =m)的数值为 能同时整除i和j的所有自然数之和.给定a,计算数表中不大于 ...
- 解题:SDOI 2014 重建
题面 做这个这个题需要稍微深入理解一点矩阵树定理:套矩阵树定理得到的东西是有意义的,它是“所有生成树边权乘积之和”(因为度数矩阵是点的边权和,邻接矩阵是边权),即$\sum_{t}\prod_{e∈t ...
- 解题:SDOI 2014 数表
题面 为了好写式子,先不管$a$的限制 设$facs$为因子和,那么有 $ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^mfacs(gcd(i,j))$ 再设$f( ...
- 【BZOJ 3530】【SDOI 2014】数数
http://www.lydsy.com/JudgeOnline/problem.php?id=3530 上午gty的测试题,爆0了qwq 类似文本生成器那道题,把AC自动机的转移建出来,准确地说建出 ...
- 「BZOJ 3529」「SDOI 2014」数表「莫比乌斯反演」
题意 有一张 \(n\times m\) 的数表,其第\(i\)行第\(j\)列的数值为能同时整除\(i\)和\(j\)的所有自然数之和. \(T\)组数据,询问对于给定的 \(n,m,a\) , 计 ...
随机推荐
- 【置换】G. Poker 2.0
https://www.bnuoj.com/v3/contest_show.php?cid=9146#problem/G [题意] 题意很简单,就是“鸽尾式”洗扑克,问洗m次各张牌的位置 [思路] 牌 ...
- (在线工具)JSON字符串转换成Java实体类(POJO)
http://www.bejson.com/json2javapojo/ 付代码代码转换示例: public static FixMixedOrderResponse serialization(St ...
- unbuntu下安装多个JAVA JDK版本及如何切换
当前环境已经安装过jdk1.6.0_45安装JDK 1.7.x时,若安装错误,可执行以下步骤:sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-ge ...
- 【BZOJ4475】子集选取(计数)
题意: 思路: #include<cstdio> #include<cstdlib> #include<iostream> #include<algorith ...
- msp430项目编程26
msp430中项目---串行存储器接口 1.I2C工作原理 2.I2C通信协议 3.代码(显示部分) 4.代码(功能实现) 5.项目总结 msp430项目编程 msp430入门学习
- CodeIgniter框架的缓存原理分解
用缓存的目的:(手册上叙述如下,已经写得很清楚了) Codeigniter 支持缓存技术,以达到最快的速度. 尽管CI已经相当高效了,但是网页中的动态内容.主机的内存CPU 和数据库读取速度等因素直接 ...
- struts2常用类型的Result
2.2.1. dispatcher dispatcher类型是用于转发的Result,可以将请求转发给JSP.这种类型的Result对应的类为 ServletDispatcherResult,它是St ...
- Fibonacci--poj3070(矩阵快速幂)
http://poj.org/problem?id=3070 Description In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn ...
- [Bzoj2120]数颜色 (非正解 )(莫队)
2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 6286 Solved: 2489[Submit][Status][Discuss] ...
- java中可以通过调用ping命令来判断网络是否连接正常
原文:http://www.open-open.com/code/view/1446382328960 import java.io.BufferedReader; import java.io.IO ...