【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\) , 计 ...
随机推荐
- HDU-2159 FATE,01背包变形
FATE 这道题和完全背包十分类似,只不过加上了忍耐度这个条件限制,所以很正常的想到用三维数组来模拟.但背包问题优化只有一层循环,这里当然也可以把种类这一层省略.d[i][j]表示杀i只怪耗费忍耐度为 ...
- Easy sssp(vijos 1053)
描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一 ...
- 【BZOJ2733】永无乡(线段树,启发式合并)
题意:支持合并,求块内K小数 对于 100%的数据 n≤100000,m≤n,q≤300000 思路:对于每一个块建立一棵动态开点的线段树,暴力(启发式?)合并后二分下就行了 merge用函数的方式写 ...
- 莫队乱搞--BZOJ2038: [2009国家集训队]小Z的袜子(hose)
$n \leq 50000$的$\leq 50000$的数字序列,$m \leq 50000$个询问,每次问一个区间中随机拿两次(不放回)拿到相同数字的概率,以既约分数形式输出. 莫队入门.把询问按“ ...
- Codeforces917D. Stranger Trees
$n \leq 100$的完全图,对每个$0 \leq K \leq n-1$问生成树中与给定的一棵树有$K$条公共边的有多少个,答案$mod \ \ 1e9+7$. 对这种“在整体中求具有某些特性的 ...
- THUWC2018 暴力+爆炸记
Day 0 没有Day0. Day 1 签到然后去宿舍,环境还行,比某偏远山区要强多了,不过这热水有点难拿??看RP有遇到煮好水的饮水机就拿,没有就苟矿泉水. 中午,那个餐还是挺好吃的,不过餐费40就 ...
- GO语言 --socket.io
socket.io是对websocket的封装以及扩展, 可以跨平台使用, 具体可看官网.. GO语言实现: package main import ( "github.com/googol ...
- 如何使用sqlalchemy获取某年某月的数据总和
代码如下: # 基于Flask的SQLAlchemy # models class History(db.Model): __tablename__ = 'historys' id = db.Colu ...
- 在SUSE12中使用 Machinery 进行高级系统管理
简单介绍 在 SUSE Linux Enterprise 12 中.SUSE 如今推出了面向系统管理员的 Machinery.作为其高级系统管理模块的一部分.Machinery 是适用于 Linux ...
- Eclipse luna 装不上 veloeclipse
今天在Eclipse中始终无法安装veloeclipse ,报错:Failed to prepare partial IU: [R]com.googlecode.veloeclipse.ui 2.0. ...