【NOI省选模拟】小奇的花园
「题目背景」
小奇在家中的花园漫步时,总是会思考一些奇怪的问题。
「问题描述」
小奇的花园有n个温室,标号为1到n,温室以及以及温室间的双向道路形成一棵树。
每个温室都种植着一种花,随着季节的变换,温室里的花的种类也在不断发生着变化。
小奇想知道从温室x走到温室y的路径中(包括两个端点),第t种花出现的次数。
「输入格式」
第一行为两个整数n,q,表示温室的数目和操作的数目。
第二行有n个整数T1,T2…Tn其中Ti表示温室i中的花的种类。
接下来n-1行,每个两个整数x, y,表示温室x和y之间有一条双向道路。
接下来q行,表示q个操作,分别为以下两种形式之一:
• C x t 表示在温室x中的花的种类变为t。
• Q x y t 表示询问温室x走到温室y的路径中(包括两个端点),第t种花出现
的次数。
为了体现在线操作,输入数据中的每个操作的参数都进行了加密。记最后一次询问的答案为anslast(一开始设anslast为0),下次读入中的x,y,t均需要异或上anslast以得到真实值,在C/C++中异或为ˆ运算符,在pascal中为xor运算符。
「输出格式」
输出q行,每行一个正整数表示该次询问答案。
「样例输入」
5 8
10 20 30 40 50
1 2
1 3
3 4
3 5
Q 2 5 10
C 2 21
Q 3 4 21
C 6 22
Q 1 7 28
C 5 20
Q 2 5 20
Q 2 0 9
「样例输出」
1
2
0
3
1
「样例解释」
加密前的操作:
Q 2 5 10
C 3 20
Q 2 5 20
C 4 20
Q 3 5 30
C 5 20
Q 2 5 20
Q 1 3 10
「数据范围」
对于30%的数据,有n <= 1000, q <= 2000。
对于50%的数据,有n <= 10000, q <= 20000。
对于100%的数据,有n <= 100000, q <= 200000,0 <= T < 2^31。
←小奇
下面的题解都是自己的话:
50%
既然强制在线,那我们就在线模拟,没什么方法,就一步步地往上找LCA并统计答案然后输出就好啦~
考场上实在没办法AC拿50分也不吃亏。
100%
有一个转化很重要。
我们可以通过类似求树上两点路径长度 dis=dep[x]+dep[y]-dep[LCA]*2 的方法,用s[i]表示从根节点到此时的i点col颜色的出现次数。
所以每次在某个节点的某个颜色出现次数增加1时,它的整个子树的每个节点的s[i]都会增加1,那么从x到y某个颜色的出现次数显然就变成 s[x]+s[y]-s[LCA]*2+val[LCA]了
那这样题目要求的单点修改、区间查询就被我们变成子树修改、单点查询了。子树修改用DFS序来看其实也就是区间修改了,可以用线段树解决。
但是颜色种类那么多怎么办呢(而且数值还那么大)?
可以用map来维护颜色编号,用动态开点线段树的方式对每一种颜色维护一棵线段树。
做本题是参考了黄学长Hzwer的题解和程序,代码可能有相似之处,但线段树的操作绝对是我自己的风格。(求资瓷~)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map> #define For(i,a,b)for(register int i=a;i<=b;++i)
#define Dwn(i,a,b)for(register int i=a;i>=b;--i)
#define Re register
#define Pn putchar('\n') using namespace std; const int N=1e5+,Nr=1e7+;
int head[N],nxt[N*],v[N*],cnt=;
int f[N][],dfx[N],dID=,dep[N],sz[N];
int rt[N*],ls[Nr],rs[Nr],tag[Nr],tr[Nr],tID=;
int n,m,x,y,T[N*],cID=,t,Q,ans=;
map<int,int>mp;
inline void read(int &v){
v=;
char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')v=v*+c-'',c=getchar();
}
void write(int x){
if(x>)write(x/);
int xx=x%;
putchar(xx+'');
}
void add(int ux,int vx){
cnt++;
nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx;
cnt++;
nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux;
} void DFS(int x,int fa){
sz[x]=;
dfx[x]=++dID;
for(Re int i=head[x];i;i=nxt[i]){
int vv=v[i];
if(vv==fa)continue;
dep[vv]=dep[x]+;
f[vv][]=x;
DFS(vv,x);
sz[x]+=sz[vv];
}
} int LCA(int x,int y){
if(dep[x]<dep[y])swap(x,y);
Dwn(b,,)if(f[x][b]!=-){
if(dep[f[x][b]]>=dep[y])x=f[x][b];
}
if(x==y)return x;
Dwn(b,,)if(f[x][b]!=-&&f[y][b]!=-&&f[x][b]!=f[y][b]){
x=f[x][b]; y=f[y][b];
}
return f[x][];
} void pDown(int o,int l,int r){
if(!tag[o]||l==r)return;
int tg=tag[o]; tag[o]=;
if(!ls[o])ls[o]=++tID;
if(!rs[o])rs[o]=++tID;
tr[ls[o]]+=tg; tag[ls[o]]+=tg;
tr[rs[o]]+=tg; tag[rs[o]]+=tg;
} void Ins(int &o,int l,int r,int lx,int rx,int dt){
if(!o)o=++tID;
if(lx<=l&&rx>=r){
tr[o]+=dt; tag[o]+=dt;
return;
}
pDown(o,l,r);
int m=(l+r)>>;
if(lx<=m)Ins(ls[o],l,m,lx,rx,dt);
if(rx>m)Ins(rs[o],m+,r,lx,rx,dt);
} int Qry(int o,int l,int r,int px){
if(!o)return ;
if(l==r)return tr[o];
pDown(o,l,r);
int m=(l+r)>>;
if(px<=m)return Qry(ls[o],l,m,px);
else return Qry(rs[o],m+,r,px);
} int main(){
freopen("garden.in","r",stdin);
freopen("garden.out","w",stdout);
read(n); read(Q);
For(i,,n){
read(t);
if(!mp[t])mp[t]=++cID;
T[i]=mp[t];
}
For(i,,n-){
read(x); read(y);
add(x,y);
} memset(f,-,sizeof(f));
DFS(,);
For(b,,) For(i,,n){
if(f[i][b-]==-)continue;
f[i][b]=f[ f[i][b-] ][b-];
} For(i,,n){
int lx=dfx[i];
int rx=dfx[i]+sz[i]-;
Ins(rt[T[i]],,n,lx,rx,);
} For(i,,Q){ char opt=getchar();
while(opt!='C'&&opt!='Q')opt=getchar();
if(opt=='C'){
read(x); read(t);
x^=ans; t^=ans;
if(!mp[t])mp[t]=++cID;
t=mp[t];
int lx=dfx[x],rx=dfx[x]+sz[x]-; Ins(rt[T[x]],,n,lx,rx,-);
Ins(rt[t],,n,lx,rx,);
T[x]=t;
}
if(opt=='Q'){
read(x); read(y); read(t);
x^=ans; y^=ans; t^=ans;
if(!mp[t])mp[t]=++cID;
t=mp[t];
int xy=LCA(x,y);
int fn;
fn=Qry(rt[t],,n,dfx[x])+Qry(rt[t],,n,dfx[y]);
fn-=Qry(rt[t],,n,dfx[xy])*;
if(T[xy]==t)fn++;
ans=fn;
write(fn); Pn;
}
}
fclose(stdin); fclose(stdout);
return ;
}
【NOI省选模拟】小奇的花园的更多相关文章
- 【Luogu】U16325小奇的花园(树链剖分)
题目链接 学了学动态开点的树链剖分,其实跟动态开点的线段树差不多啦 查询的时候别ssbb地动态开点,如果没这个点果断返回0就行 只要注意花的种类能到intmax就行qwq!!!! #include&l ...
- 【NOI广东省选模拟赛】割
[问题描述] 给出 n 个数 a1,a2,...,an, 询问有多少个三元组(i, j, k)满足以下两个条件:1. i < j < k: 2. ai*aj*ak 是 p 的倍数. [输入 ...
- 小奇模拟赛9.13 by hzwer
2015年9月13日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿(explo) [题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞 ...
- 【NOIP模拟赛】小奇的矩阵
[题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个n*m的矩阵,矩阵中的每个元素aij为正整数. 接下来规定 1.合法的路径初始从矩阵左上角出发,每次只能向右或向下走,终点为右下 ...
- 【NOIP模拟赛】小奇挖矿 2
[题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市场,以便为飞船升级无限非概率引擎. [问题描述] 现在有m+1个星球,从左到右标号为0到m,小奇最初在0 ...
- NOIP模拟赛(by hzwer) T2 小奇的序列
[题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...
- NOIP模拟赛(by hzwer) T3 小奇回地球
[题目背景] 开学了,小奇在回地球的路上,遇到了一个棘手的问题. [问题描述] 简单来说,它要从标号为 1 的星球到标号为 n 的星球,某一些星球之间有航线. 由于超时空隧道的存在,从一个星球到另一个 ...
- NOIP模拟赛(by hzwer) T1 小奇挖矿
[题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值 w)的飞船,按既定 路线依次飞过喵星系的 n 个星球. [问题描述] 星球分为 2 类:资源型和维修型. 1. 资源型:含矿物质量 ...
- [CSP-S模拟测试]:小奇的仓库(warehouse)(树形DP)
题目背景 小奇采的矿实在太多了,它准备在喵星系建个矿石仓库.令它无语的是,喵星系的货运飞船引擎还停留在上元时代! 题目描述 喵星系有$n$个星球,星球以及星球间的航线形成一棵树.从星球$a$到星球$b ...
随机推荐
- openssl之BIO系列之20---缓冲(buffer)类型BIO
缓冲(buffer)类型BIO ---依据openssl doc\crypto\bio_f_buffer.pod翻译和自己的理解写成 (作者:DragonKing, Mail: wzhah@263.n ...
- AndroidPageObjectTest_Simple.java
以下代码使用ApiDemos-debug.apk进行测试 //这个脚本用于演示PageFactory的功能:使用注解@FindBy.@AndroidFindBy.@IOSFindBy定位元素.注解用法 ...
- Matlab小技巧之怎么复制汉字
在我们复制Matlab到Word的过程中,经常会出现乱码的情况.这时候可以这么做. 1.复制Matlab代码. 2.新建一个txt文件,将代码粘贴到txt文件中. 3.复制txt文件中的代码到Word ...
- pypi指定下载源
pip install -i http://pypi.douban.com/simple/ scipy==0.19.0
- cassandra 存储list数组
demo如下: CREATE TABLE users3 ( user_id text PRIMARY KEY, first_name text, last_name text, emails list ...
- H3C-交换机密码恢复
交换机密码恢复: 一. 拔掉电源再插上重新启动交换机,在超级终端中可以看到交换机启动画面,当出现提示按CTRL+B时,此时按住CTRL+B,我们会看到有9个选项: 1. download applic ...
- java实现EXCEL数据导入到数据库中的格式问题的解决
之前作为项目甲方,加之java接触不多,在java web开发方面都是打下手的份. 对于EXCEL数据导入到数据库这个问题一直老是出现格式原因而导入失败也是未免惆怅,开发团队也是只说回去检查一下格式. ...
- 数据表示Numpy
1 基本 1.1 基本介绍 掌握表示, 清洗, 统计和展示数据的能力 Numpy, Matplotlib, Pandas, Projects 摘要: 有损的提取数据特征的过程 可以将一组数据, 摘要出 ...
- 「LOJ#10015」「一本通 1.2 练习 2」扩散(并查集
题目描述 一个点每过一个单位时间就会向 444 个方向扩散一个距离,如图所示:两个点 a .b 连通,记作 e(a,b),当且仅当 a .b的扩散区域有公共部分.连通块的定义是块内的任意两个点 u.v ...
- darknet源码学习
darknet是一个较为轻型的完全基于C与CUDA的开源深度学习框架,其主要特点就是容易安装,没有任何依赖项(OpenCV都可以不用),移植性非常好,支持CPU与GPU两种计算方式.1.test源码( ...