P3313 [SDOI2014]旅行

题目描述

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

为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。

在S国的历史上常会发生以下几种事件:

“CC x c“:城市x的居民全体改信了c教;

“CW x w“:城市x的评级调整为w;

“QS x y“:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;

“QM x y“:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级最大值。

由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

输入输出格式

输入格式:

输入的第一行包含整数N,Q依次表示城市数和事件数。

接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的评级和信仰。 接下来N-1行每行两个整数x,y表示一条双向道路。

接下来Q行,每行一个操作,格式如上所述。

输出格式:

对每个QS和QM事件,输出一行,表示旅行者记下的数字。

说明

N,Q < =10^5 , C < =10^5

数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时

刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。


首先把题目细节读到位,第一行有“用N-1条双向道路连接”,这是一颗树。树中每个点都有一些不同的属性,当走过一条链时,只询问链上一种属性的点。

对于树链操作,我们考虑用树剖维护;对于每种属性的点,我们分别建立一颗线段树来维护。

值得一提的是,建很多个线段树的方法大多数被称为主席树,其实这么理解没什么问题,但如果可以的话,我更想用动态开点线段树来称呼它(通过 只建立需要访问的点的所在链 以达到节省空间的目的)

而主席树基础做法:静态区间维护第K大值,则是基于节点共用以节省空间的。


#include <cstdio>
#define ls t[id].ch[0]
#define rs t[id].ch[1]
#define mid (l+r>>1)
#define Mid (L+R>>1)
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
const int N=100010;
int head[N],cnt=0,next[N<<1],to[N<<1];
int f[N],siz[N],dfn[N],ws[N],top[N],dep[N],time=0;
void add(int u,int v){next[++cnt]=head[u];to[cnt]=v;head[u]=cnt;}
void dfs1(int now)
{
for(int i=head[now];i;i=next[i])
{
int v=to[i];
if(f[now]!=v)
{
f[v]=now;
dep[v]=dep[now]+1;
dfs1(v);
siz[now]+=siz[v];
if(siz[ws[now]]<siz[v])
ws[now]=v;
}
}
siz[now]++;
}
void dfs2(int now,int anc)
{
dfn[now]=++time;
top[now]=anc;
if(!ws[now]) return;
dfs2(ws[now],anc);
for(int i=head[now];i;i=next[i])
{
int v=to[i];
if(!dfn[v])
dfs2(v,v);
}
}
struct node
{
int ch[2],mx,sum;
}t[N*25];
int tot=0,typ[N],c[N],root[N],n,q;
int New(int dat)
{
t[++tot].mx=dat,t[tot].sum=dat;
return tot;
}
int change(int id,int l,int r,int loc,int dat)
{
if(!id) id=New(dat);
if(l==r) {t[id].mx=dat;t[id].sum=dat;return id;}
if(loc<=mid) ls=change(ls,l,mid,loc,dat);
else rs=change(rs,mid+1,r,loc,dat);
t[id].mx=max(t[ls].mx,t[rs].mx);
t[id].sum=t[ls].sum+t[rs].sum;
return id;
}
int query_s(int id,int L,int R,int l,int r)
{
if(!id) return 0;
if(L==l&&R==r) return t[id].sum;
if(r<=Mid) return query_s(ls,L,Mid,l,r);
else if(l>Mid) return query_s(rs,Mid+1,R,l,r);
else return query_s(ls,L,Mid,l,Mid)+query_s(rs,Mid+1,R,Mid+1,r);
}
int query_m(int id,int L,int R,int l,int r)
{
if(!id) return 0;
if(L==l&&R==r) return t[id].mx;
if(r<=Mid) return query_m(ls,L,Mid,l,r);
else if(l>Mid) return query_m(rs,Mid+1,R,l,r);
else return max(query_m(ls,L,Mid,l,Mid),query_m(rs,Mid+1,R,Mid+1,r));
}
void t_Q_sum(int x,int y)
{
int ty=typ[x],ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
ans+=query_s(root[ty],1,n,dfn[top[x]],dfn[x]);
x=f[top[x]];
}
else
{
ans+=query_s(root[ty],1,n,dfn[top[y]],dfn[y]);
y=f[top[y]];
}
}
ans+=query_s(root[ty],1,n,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]));
printf("%d\n",ans);
}
void t_Q_mx(int x,int y)
{
int ty=typ[x],ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
ans=max(ans,query_m(root[ty],1,n,dfn[top[x]],dfn[x]));
x=f[top[x]];
}
else
{
ans=max(ans,query_m(root[ty],1,n,dfn[top[y]],dfn[y]));
y=f[top[y]];
}
}
ans=max(ans,query_m(root[ty],1,n,min(dfn[x],dfn[y]),max(dfn[x],dfn[y])));
printf("%d\n",ans);
}
int main()
{
scanf("%d%d",&n,&q);
int u,v;
for(int i=1;i<=n;i++) scanf("%d%d",c+i,typ+i);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dfs1(1);
dfs2(1,1);
for(int i=1;i<=n;i++)
root[typ[i]]=change(root[typ[i]],1,n,dfn[i],c[i]);
for(int i=1;i<=q;i++)
{
int x,y;char opt[18];
scanf("%s%d%d",opt,&x,&y);
if(opt[1]=='C')
{
root[typ[x]]=change(root[typ[x]],1,n,dfn[x],0);
typ[x]=y;
root[typ[x]]=change(root[typ[x]],1,n,dfn[x],c[x]);
}
else if(opt[1]=='W')
{
root[typ[x]]=change(root[typ[x]],1,n,dfn[x],y);
c[x]=y;
}
else if(opt[1]=='S')
t_Q_sum(x,y);
else
t_Q_mx(x,y);
}
return 0;
}

2018.6.17

洛谷 P3313 [SDOI2014]旅行 解题报告的更多相关文章

  1. 洛谷 P3312 [SDOI2014]数表 解题报告

    P3312 [SDOI2014]数表 题目描述 有一张\(N*M\)的数表,其第\(i\)行第\(j\)列(\(1\le i \le n\),\(1 \le j \le m\))的数值为能同时整除\( ...

  2. 洛谷 P3313 [SDOI2014]旅行

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

  3. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

  4. 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)

    题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...

  5. 洛谷 P1783 海滩防御 解题报告

    P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...

  6. 洛谷 P4597 序列sequence 解题报告

    P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...

  7. 洛谷1087 FBI树 解题报告

    洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...

  8. 洛谷 P4568 [JLOI2011]飞行路线 解题报告

    P4568 [JLOI2011]飞行路线 题目描述 Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在\(n\)个城市设有业务,设这些城市分别标记为0到\(n−1\ ...

  9. [SDOI2014]旅行解题报告

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

随机推荐

  1. WebApi 异步请求(HttpClient)

    还是那几句话: 学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现在,学习代表你的将来 废话不多说,直接进入正题: 今天公司总部要求各个分公司把短信接口对接上,所谓的 ...

  2. FreeCAD源码初步了解

    FreeCAD简介 FreeCAD是基于OpenCASCADE的开源CAD/CAE软件,完全开源(GPL的LGPL许可证),官方源码地址,详情可参考维基百科,百度百科等等. 如果要编译FreeCAD, ...

  3. Mysql读写分离方案-MySQL Proxy环境部署记录

    Mysql的读写分离可以使用MySQL Proxy和Amoeba实现,其实也可以使用MySQL-MMM实现读写分离的自动切换.MySQL Proxy有一项强大功能是实现"读写分离" ...

  4. sublime text3 安装package control 出现问题解决过程记录

    1.安装package control 失败 通过最简单的自动安装 package control 失败(详见package control官网). 报错展示: File "./python ...

  5. omnigraffle 的一些总结

    http://jingyan.baidu.com/article/fcb5aff7a16337edab4a714d.html Omnigraffle绘制连接线时从任意点开始 点击直线工具后,在右侧设置 ...

  6. Visual Studio2015安装过程以及单元测试

    安装环境: 安装版本: Visual Studio2015 安装过程: 因为我是在第一次老师安排的作业的时候感觉VC++6.0不如VS方便所以才装的Visual Studio2015,又安装了点插件, ...

  7. Daily Scrumming* 2015.12.21(Day 13)

    一.团队scrum meeting照片 大部分成员编译请假,故今天没有开scrum meeting 二.成员工作总结 姓名 任务ID 迁入记录 江昊 无 无 任务说明: 今日准备编译测验,请假 遇到问 ...

  8. Linux内核读书笔记第五周链接

    1.临界区(critical regions)就是访问和操作共享数据的代码段.多个执行线程并发访问同一个资源通常是不安全的,为了避免在临界区中并发访问,编程者必须保证这些代码 原子地执行.也就是说,代 ...

  9. 软件工程项目之摄影App

    摄影app 开发人员:Ives & Dyh 开发功能: 摄影师注册与认证,为年轻摄影师提供成长的空间,发挥一技之长的平台. 用户注册与验证,为有摄影需求的人提供选择摄影师进行个性化拍摄的平台. ...

  10. [2017BUAA软工]个人项目

    软工个人项目 一.Github项目地址 https://github.com/Lydia-yang/2017BUAA-SoftwareEngineering 二.解题思路 在刚开始拿到题目的时候,关于 ...