题目描述

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,并记下了途中留宿过的城市的评级最大值。

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

                    --by luogu

http://daniu.luogu.org/problem/show?pid=3313



得到模型——询问树上两点间路径中符合条件的点的加和与最值,支持单点修改权值和条件;

考虑建立C(宗教数)棵线段树——然后内存显然不够,

但可以不把她们开满:

如对于宗教i所属的线段树,只有属于宗教i的叶节点以及其祖先结构被建立;

相当于每个叶节点连一条向相应根的树链;

于是c棵线段树等价于n-条树链;

nlogn级内存;

对于每次宗教修改:

把原树上该点的权值清零,在该点的新宗教的树中建一条通向她的树链,为了方便下次修改,记得把原数组中的宗教值修改;

对于每次权值修改:

直接修改即可;

一个优化:

每次修改时动态的把已经为零的树链断开;

这样貌似可以减小查询的常数(因为当查询到不存在的树链时会直接返回)

然而实际评测时发现仿佛没什么用

代码如下:(精简而合适的代码)

 #include<cstdio>
#include<cstring>
const int MAXN=;
int n,m,L,R;
int reli[MAXN],dis[MAXN],dep[MAXN],size[MAXN],fa[MAXN],hine[MAXN],rank[MAXN],top[MAXN],a[MAXN];
struct pool{
int sum,ls,rs,max;
}data[MAXN*];
int tot;
int root[MAXN];
struct ss{
int next,to;
}e[MAXN<<];
int first[MAXN],num;
void swap(int& a,int& b){int i=a;a=b;b=i;}
void Init();
void build(int ,int );
void dfs_1(int );
void dfs_2(int ,int );
void work();
void chan_reli(int ,int );
void chan_sum(int ,int );
void get(int ,int ,int );
void up(int );
void builine(int ,int ,int&,int ,int );
int g_sum(int ,int ,int );
int g_max(int ,int ,int );
int main()
{
Init();
work();
return ;
}
void Init(){
int i,j,k;
memset(dep,,sizeof(dep));
memset(size,,sizeof(size));
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)
scanf("%d%d",&dis[i],&reli[i]);
for(i=;i<n;i++){
hine[i]=i;
scanf("%d%d",&j,&k);
build(j,k);build(k,j);
}
hine[n]=n;dep[]=;
dfs_1();num=;
dfs_2(,);num=;
for(i=;i<=n;i++)
builine(,n,root[reli[a[i]]],i,dis[a[i]]);
}
void build(int f,int t){
e[++num].next=first[f];
e[num].to=t;
first[f]=num;
}
void dfs_1(int now){
int i;
for(i=first[now];i;i=e[i].next)
if(!dep[e[i].to]){
dep[e[i].to]=dep[now]+;
fa[e[i].to]=now;
dfs_1(e[i].to);
size[now]+=size[e[i].to];
if(hine[now]==now||size[e[i].to]>size[hine[now]])
hine[now]=e[i].to;
}
size[now]++;
}
void dfs_2(int now,int now_top){
int i;
top[now]=now_top;
rank[now]=++num;
a[num]=now;
if(hine[now]!=now)
dfs_2(hine[now],now_top);
for(i=first[now];i;i=e[i].next)
if(dep[e[i].to]==dep[now]+&&e[i].to!=hine[now])
dfs_2(e[i].to,e[i].to);
}
void work(){
int i,j,k,u,v;
char s[];
for(i=;i<=m;i++){
scanf("%s%d%d",s,&u,&v);
switch(s[]){
case 'C':chan_reli(u,v);break;
case 'W':chan_sum(u,v);break;
case 'S':get(u,v,);break;
case 'M':get(u,v,);break;
}
}
}
void chan_reli(int u,int v){
builine(,n,root[v],rank[u],dis[u]);
builine(,n,root[reli[u]],rank[u],);
reli[u]=v;
}
void chan_sum(int u,int v){
builine(,n,root[reli[u]],rank[u],v);
dis[u]=v;
}
void get(int u,int v,int kind){
int ans=,ro=root[reli[u]],i,j,k;
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]){
L=rank[top[u]];R=rank[u];
u=fa[top[u]];
}
else{
L=rank[top[v]];R=rank[v];
v=fa[top[v]];
}
if(!kind)
ans+=g_sum(,n,ro);
else{
i=g_max(,n,ro);
if(i>ans)ans=i;
}
}
if(dep[u]>dep[v]){
swap(u,v);
}
L=rank[u];R=rank[v];
if(!kind)
ans+=g_sum(,n,ro);
else{
i=g_max(,n,ro);
if(i>ans)ans=i;
}
printf("%d\n",ans);
}
void up(int nu){
data[nu].sum=data[data[nu].ls].sum+data[data[nu].rs].sum;
data[nu].max=data[data[nu].ls].max>data[data[nu].rs].max?data[data[nu].ls].max:data[data[nu].rs].max;
}
void builine(int l,int r,int&now,int x,int sum){
if(!now){
now=++tot;
}
if(l==r){
data[now].sum=sum;
data[now].max=sum;
return ;
}
int mid=(l+r)>>;
if(x<=mid)
builine(l,mid,data[now].ls,x,sum);
else
builine(mid+,r,data[now].rs,x,sum);
up(now);
if(!data[now].sum)now=;
}
int g_sum(int l,int r,int now){
if(!now)
return ;
if(L<=l&&r<=R)
return data[now].sum;
int mid=(l+r)>>,ans=;
if(L<=mid)
ans+=g_sum(l,mid,data[now].ls);
if(R>mid)
ans+=g_sum(mid+,r,data[now].rs);
return ans;
}
int g_max(int l,int r,int now){
if(!now)
return ;
if(L<=l&&r<=R)
return data[now].max;
int mid=(l+r)>>,lm=,rm=;
if(L<=mid)
lm=g_max(l,mid,data[now].ls);
if(R>mid)
rm=g_max(mid+,r,data[now].rs);
if(lm>=rm)
return lm;
return rm;
}

祝AC

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

  1. 洛谷 P3313 [SDOI2014]旅行 解题报告

    P3313 [SDOI2014]旅行 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教 ...

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

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

  3. hdu 2066 一个人的旅行 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2066 题目意思:给出T条路,和草儿家相邻的城市编号,以及草儿想去的地方的编号.问从草儿家到达草儿想去的 ...

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

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

  5. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  6. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

  7. BZOJ 1051 最受欢迎的牛 解题报告

    题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[S ...

  8. 习题:codevs 2822 爱在心中 解题报告

    这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...

  9. 习题:codevs 1035 火车停留解题报告

    本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...

随机推荐

  1. 兼容各浏览器的js回车事件

    HTML代码: <input type="text" onkeydown="EnterPress(event)" /> JS代码: function ...

  2. 总结day26 ----验证客户端的合法性,已经操作系统,进程的简单初识别

    前情提要 一:验证客户端的合法性: # .需要认证 # 程序和用户打交道的时候才会用到用户认证 # 对所有的客户端进行统一的认证 # # 我现在要做的事情 # 写一个server端 # 写一个clie ...

  3. [原创]Laravel 的缓存源码解析

    目录 前言 使用 源码 Cache Facade CacheManager Repository Store 前言 Laravel 支持多种缓存系统, 并提供了统一的api接口. (Laravel 5 ...

  4. 2016级算法第六次上机-B.ModricWang's FFT : EASY VERSION

    1114 ModricWang's FFT EASY VERSION 思路 利用FFT做大整数乘法,实际上是把大整数变成多项式,然后做多项式乘法. 例如,对于\(1234\),改写成\(f(x)=1* ...

  5. Python3 操作系统与路径 模块(os / os.path / pathlib)

    #!/usr/bin/env python # coding=utf-8 __author__ = 'Luzhuo' __date__ = '2017/5/7' import os def os_de ...

  6. 06-图2 Saving James Bond - Easy Version (25 分)

    This time let us consider the situation in the movie "Live and Let Die" in which James Bon ...

  7. 【算法笔记】A1060 Are They Equal

    1060 Are They Equal (25 分)   If a machine can save only 3 significant digits, the float numbers 1230 ...

  8. windows下python3.7.2内置venv虚拟环境下pyinstaller错误问题

    起因 开发一直使用python -m venv .pyenv 方式创建虚拟环境,在利用pyinstaller打包发布应用时,出现错误 3178 INFO: Warnings written to C: ...

  9. 利用CSS 修改input=radio的默认样式(改成选择框)

    html部分: <input id="item2" type="radio" name="item"> <label fo ...

  10. 四大组件之Activity——生命周期

    1.完整的Activity生命周期 包括onCreate() -> onStart() -> onResume() -> onPause() -> onStop -> o ...