问题描述

费了一番功夫,神犇 CJK 终于完成了前三道题目。“不错,不愧是新一代神犇啊!” JesseLiu 满意地说道,“不过,你在算法方面的功底固然不错。对于数据结构的运用,你又掌握地如何呢?”

听到“数据结构”这四个字,就连身为神犇的 CJK 也不禁吓出一身冷汗。“年轻人,现在,对于我给定一棵树,你需要完成以下操作:

1.修改某个点的权值;

2.查询某两点间路径上所有点的权值和;

3.查询某点子树的权值和。”

CJK 脸上闪过一丝不屑:不就是道链剖裸题吗?

“这只是第一问。”JesseLiu 似乎也觉得这道题太水了,于是补充道:“完成以上所有操作后,我还会有以下几种询问:

  1. 询问某个点子树上有多少个点的权值小于等于 k;
  2. 询问某两点之间的路径上有多少点的权值小于等于 k;”

尽管 CJK 是神犇,但遇到这种题,也不禁感到一丝恐惧。还好,通过自己的玄学力量,他联系到了他的同学——你。现在,就请你 A 掉这最后一道水题。

输入格式

第一行一个数 n,表示点的总数。接下来 n-1 行,一行两个整数 x 和 y,表示x 和 y 之间有边相连。接下来一个整数 m1,表示第一问中操作的数量。接下来m1 行表示操作,格式如下:

“1 x y”将点 x 的权值修改为 y;

“2 x y”询问 x 到 y 路径上的点权之和(包括 x 和 y);

“3 x”询问 x 的子树上的点权和(包括 x);

接下来一行 m2,表示第二问中操作的数量。接下来 m2 行描述操作,格式如下:

“1 x y z”询问 x 到 y 的路径上有多少个点的权值小于等于 z;

“2 x y”询问 x 的子树上有多少个点的权值小于等于 y;

每个点的初始权值为 0。

输出格式

对于每一次询问,输出一个整数表示询问的答案。

样例输入输出

样例输入1

3

1 2

1 3

3

1 1 3

1 3 1

3 1

2

2 1 2

1 1 3 1

样例输出1

4

2

1

样例输入2

5

1 2

1 3

3 4

3 5

5

3 1

1 3 1

2 4 5

1 4 -1

3 3

2

1 1 5 0

2 3 -1

解析

对于第一问,显然是一道树链剖分单点修改加区间查询和的裸题,直接做即可。

对于第二问,一个点要产生贡献,当且仅当这个点在查询的范围内(子树or路径),产生的贡献为1。为了满足限制,我们需要保证在询问时,除了小于等于询问值的节点的值为1以外其余节点都为0。我们可以想到,将询问与节点一起记在一个操作数组中,按照第一问的权值或者询问的值从小到大排序。每一个节点视为一个将节点对应的值变为1的操作,询问同第一问。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 500002
using namespace std;
struct opt{
int op,id,x,y,val;
}a[N];
int head[N],ver[N*2],nxt[N*2],l;
int n,m1,m2,i,dfn[N],end[N],tim,ans[N];
int fa[N],size[N],top[N],son[N],dep[N],pos[N],tree[N],cnt;
void insert(int x,int y)
{
l++;
ver[l]=y;
nxt[l]=head[x];
head[x]=l;
}
void dfs1(int x)
{
size[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(y!=fa[x]){
fa[y]=x;
dep[y]=dep[x]+1;
dfs1(y);
if(size[son[x]]<size[y]) son[x]=y;
size[x]+=size[y];
}
}
}
void dfs2(int x,int tp)
{
dfn[x]=++tim;
pos[x]=++cnt;top[x]=tp;
if(son[x]) dfs2(son[x],top[x]);
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(y!=son[x]&&y!=fa[x]) dfs2(y,y);
}
end[x]=tim;
}
void update(int p,int l,int r,int x,int val)
{
if(x<l||r<x) return;
if(l==r){
tree[p]=val;
return;
}
int mid=(l+r)/2;
update(p*2,l,mid,x,val);
update(p*2+1,mid+1,r,x,val);
tree[p]=tree[p*2]+tree[p*2+1];
}
int ask(int p,int l,int r,int ql,int qr)
{
if(r<ql||l>qr) return 0;
if(l>=ql&&r<=qr) return tree[p];
int mid=(l+r)/2;
return ask(p*2,l,mid,ql,qr)+ask(p*2+1,mid+1,r,ql,qr);
}
int find(int u,int v)
{
int f1=top[u],f2=top[v],ans=0;
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(f1,f2),swap(u,v);
ans+=ask(1,1,n,pos[f1],pos[u]);
u=fa[f1];f1=top[u];
}
if(dep[u]>dep[v]) swap(u,v);
return ans+ask(1,1,n,pos[u],pos[v]);
}
int my_comp(const opt &a,const opt &b)
{
if(a.val==b.val) return a.op<b.op;
return a.val<b.val;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
cin>>n;
for(i=1;i<n;i++){
int u,v;
cin>>u>>v;
insert(u,v);
insert(v,u);
}
dfs1(1);
dfs2(1,1);
cin>>m1;
for(i=1;i<=m1;i++){
int op,x,y;
cin>>op;
if(op==1){
cin>>x>>y;
update(1,1,n,pos[x],y);
}
else if(op==2){
cin>>x>>y;
cout<<find(x,y)<<endl;
}
else{
cin>>x;
cout<<ask(1,1,n,dfn[x],end[x])<<endl;
}
}
cin>>m2;
int tmp=m2;
for(i=1;i<=m2;i++){
int op,x,y,z;
cin>>op;
if(op==1){
cin>>x>>y>>z;
a[i]=(opt){op,i,x,y,z};
}
else{
cin>>x>>y;
a[i]=(opt){op,i,x,0,y};
}
}
for(i=1;i<=n;i++) a[++m2]=(opt){0,m2,i,0,ask(1,1,n,pos[i],pos[i])};
memset(tree,0,sizeof(tree));
sort(a+1,a+m2+1,my_comp);
for(i=1;i<=m2;i++){
if(a[i].op==0) update(1,1,n,pos[a[i].x],1);
else if(a[i].op==1) ans[a[i].id]=find(a[i].x,a[i].y);
else ans[a[i].id]=ask(1,1,n,dfn[a[i].x],end[a[i].x]);
}
for(i=1;i<=tmp;i++) cout<<ans[i]<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}

总结

一个思路:为了消去影响,可以使一个影响产生在询问以后,通过排序以及适当的转化实现。

Test 6.29 T4 简单数据结构练习的更多相关文章

  1. python学习总结----简单数据结构

    mini-web服务器 - 能够完成简单的请求处理 - 使用http协议 - 目的:加深对网络编程的认识.为后面阶段学习web做铺垫 简单数据结构 - 排列组合 import itertools # ...

  2. 牛客练习赛22-E.简单数据结构1(扩展欧拉定理降幂 +树状数组)

    链接:E.简单数据结构1 题意: 给一个长为n的序列,m次操作,每次操作: 1.区间加 2.对于区间,查询 ,一直到- 请注意每次的模数不同.   题解:扩展欧拉定理降幂 对一个数p取log(p)次的 ...

  3. [LOJ#2326]「清华集训 2017」简单数据结构

    [LOJ#2326]「清华集训 2017」简单数据结构 试题描述 参加完IOI2018之后就是姚班面试.而你,由于讨厌物理.并且想成为乔布斯一样的创业家,被成功踢回贵系. 转眼,时间的指针被指向201 ...

  4. 简单数据结构题(from 钟子谦——IOI2018集训队自选题)

    简单数据结构题(from 钟子谦--IOI2018集训队自选题) 试题描述 给一棵 \(n\) 个点的树,点权开始为 \(0\) ,有 \(q\) 次操作,每次操作是选择一个点,把周围一圈点点权 \( ...

  5. 简单数据结构———AVL树

    C - 万恶的二叉树 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     64b ...

  6. NYOJ 简单数据结构

    NYOJ 2 括号配对问题 栈的简单应用.可使用STL. #include <iostream> #include <cstdio> #include <cstring& ...

  7. 冬训day3 简单数据结构

    A - 简单计算器 模拟加栈..写一写就好,从头到尾扫一遍,分两个栈存,一个存运算符,一个存中间结果,遇到乘除就先处理了,每次遇到加减就处理上一个加减的两个数,结果压进去...同时把这个运算符存进去. ...

  8. 【正睿多校联盟Day4 T4 简单的数论题】

    题目名有毒 由于并没有系统地开始学习数论,所以数论题基本靠暴力. 然鹅本题的题解相当简单: emmm....我当你没说 一个简单易懂的方法是这样的: 1. 欧拉定理的推论 若正整数a,n互质,则对于任 ...

  9. 【简单数据结构】并查集--洛谷 P1111

    题目背景 AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数NN,和公路数MM,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你 ...

随机推荐

  1. ORACLE DG临时表空间管理

    实施目标:由于磁盘空间不足,将主库的临时表空间修改位置 standby_file_management 管理方式:AUTO SQL> show parameter standby_file NA ...

  2. 自定义控件 - 切换开关:SwitchView

    自定义控件一般的几个步骤:1.初始化相关背景图片,布局文件,自定义属性2.设置控件宽高OnMeasure()3.布局或者排版OnLayout()4.绘制控件OnDraw()5.处理触摸事件OnTouc ...

  3. 如何查看yum安装的程序包都放在哪些地方了?

    yum安装, 是先下载下来, 然后安装, 用dnf代替yum后, 配置文件跟yum类似, 也是放在 /etc/dnf/ 目录下的, 也有dnf.conf 配置文件等 dnf list后面还可以跟参数: ...

  4. Vue实战:音乐播放器(一) 页面效果

    先看一下效果图 首页 歌单详情页 歌手列表 歌手详情页 排行页面 榜单的详情页(排序样式) 搜索页面 搜索结果 播放器内核 歌词自动滚动 播放列表 用户中心

  5. VMware 虚拟化编程(3) —VMware vSphere Web Service API 解析

    目录 目录 前文列表 VMware vSphere Web Services API VMware vSphere Web Services SDK vSphere WS API 中的托管对象 Man ...

  6. 常用的adb命令收集

    测试app常会用到一些adb命令,当然使用adb命令,需要配好jdk.sdk环境,不然不能使用的 1.adb help ----帮助信息 2.adb device ----手机的id查看 3.adb ...

  7. spring的基础配置

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  8. idea中gradle的springboot的项目热部署

    1:在build.gradle中添加热部署依赖(我gradle版本是5.5.1) // 添加 热部署依赖implementation 'org.springframework.boot:spring- ...

  9. powerdisigner

  10. Linux 系统下的7个运行级别

    转自:http://blog.chinaunix.net/uid-22746363-id-383989.html Linux系统有7个运行级别(runlevel)运行级别0:系统停机状态,系统默认运行 ...