题目传送门

题意:初始有n棵树,每棵树都只有1个n号节点,现在有m次添加操作,每次操作是将$[l,r]$范围内的树的$u$节点后面添加一个$v$节点。每个v节点只会被添加一次。

  然后是q次询问,输出$[l,r]$范围内的树$x$节点的子树大小之和。

思路:由于每个节点被当成子节点添加到树上只会被添加一次,所以假设直接将节点连到一棵树上,按照dfs排序之后,x节点的子树dfs序必定是连续的。

  考虑主席树,我们以dfs序为主席树的版本,每个节点就让$(ql,qr)$之间的树加一,最后只需要将ou[x]和in[x]-1这两个版本之间的主席树相减即可。(代码在最下方)

  另一个做法:考虑扫描线,我们还是先处理处dfs序,对于节点x的求解,我们可以分解成,减去x之前所有节点(ql,qr)的值,再加上ou[x]的(ql,qr)的值,就得到了我们要的答案。所以我们还是按dfs序处理线段树,将每一个节点的影响加入线段树后,再处理这个节点需要加减的地方即可。我自己没有写过扫描线版本,此处引用一位朋友的代码。

//这是扫描线的关键,此处的线段树就是一个普通的区间求和的线段树。    
scanf("%d", &q);
for(int i = ; i <= q; i++) {
int x, l, r;
scanf("%d%d%d", &x, &l, &r);
V[in[x] - ].push_back(Qus{-, l, r, i});
V[ot[x]].push_back(Qus{, l, r, i});
}
for(int i = ; i <= idx; i++) {
Tree.update(L[rk[i]], R[rk[i]], , , n, );
for(auto t : V[i]) {
ans[t.id] += t.op * Tree.query(t.l, t.r, , n, );
}
}
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,b,a) for(int i=b;i>=a;i--)
#define clr(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pii pair<int,int >
using namespace std;
typedef long long ll;
ll rd()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int maxn=;
const int inf=0x3f3f3f3f;
int n,m,q,tot,root[maxn],l[maxn],r[maxn],in[maxn],ou[maxn],re[maxn],ti;
struct node{
int l,r;
ll sum,lazy;
}tr[maxn*];
vector<int >ve[maxn];
void dfs(int u){
in[u]=++ti;
re[ti]=u;
for(auto it:ve[u]){
dfs(it);
}
ou[u]=ti;
}
void update(int &rt,int pre,int l,int r,int ql,int qr,ll val){
tr[rt=++tot]=tr[pre];
tr[rt].sum+=(qr-ql+)*val;
if(ql<=l&&r<=qr){
tr[rt].lazy+=val;
return;
}
int mid=(l+r)>>;
if(ql<=mid)update(tr[rt].l,tr[pre].l,l,mid,ql,min(qr,mid),val);
if(mid<qr)update(tr[rt].r,tr[pre].r,mid+,r,max(mid+,ql),qr,val);
}
ll query(int rt,int pre,int l,int r,int ql,int qr,ll add){
if(ql<=l&&r<=qr){
return tr[rt].sum-tr[pre].sum+(r-l+)*add;
}
add+=tr[rt].lazy-tr[pre].lazy;
int mid=(l+r)>>;
ll res=;
if(ql<=mid)res+=query(tr[rt].l,tr[pre].l,l,mid,ql,qr,add);
if(mid<qr)res+=query(tr[rt].r,tr[pre].r,mid+,r,ql,qr,add);
return res; }
int main(){
cin>>n>>m;
l[]=,r[]=n;
for(int i=;i<=m;i++){
int u,v,x,y;
u=rd(),v=rd(),x=rd(),y=rd();
ve[u].pb(v);
l[v]=x,r[v]=y;
}
dfs();
for(int i=;i<=ti;i++){
int u=re[i];
update(root[i],root[i-],,n,l[u],r[u],);
}
cin>>q;
rep(i,,q){
int x,ql,qr;
x=rd(),ql=rd(),qr=rd();
printf("%lld\n",query(root[ou[x]],root[in[x]-],,n,ql,qr,));
}
}

2019牛客暑期多校训练营(第八场)I-Inner World DFS序+主席树(扫描线也可)的更多相关文章

  1. 2019牛客暑期多校训练营(第九场)H Cutting Bamboos(主席树+二分)

    题意:n个竹子,有高度,q次询问,询问之间是独立的,每次查询输入l,r,x,y代表砍区间[l,r]]内的竹子砍y次,最后一次要砍成0,每次砍掉的总长度相同,问第x次砍的高度是多少. 既然每次要求砍掉的 ...

  2. 2019牛客暑期多校训练营(第一场)I Points Division(dp+线段树优化)

    给你n个点,第i个点在的位置为(xi,yi),有两个属性值(ai,bi).现在让你把这n个点划分为A和B两个部分,使得最后不存在i∈A和j∈B,使得xi>=xj且yi<=yj.然后对于所有 ...

  3. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  4. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  5. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

  6. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  7. 2019牛客暑期多校训练营(第二场)F.Partition problem

    链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...

  8. 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...

  9. [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem

    链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...

  10. 2019牛客暑期多校训练营(第二场)J-Subarray(思维)

    >传送门< 前言 这题我前前后后看了三遍,每次都是把网上相关的博客和通过代码认真看了再思考,然并卵,最后终于第三遍也就是现在终于看懂了,其实懂了之后发现其实没有那么难,但是的的确确需要思维 ...

随机推荐

  1. 前端(二十一)—— vue指令:文本类指令、避免页面闪烁、v-bind指令、v-on指令、v-model指令、条件渲染指令、列表渲染指令

    文本类指令.v-bind指令.v-on指令.v-model指令.条件渲染指令.列表渲染指令 一.文本操作 v-text:文本变量 <p v-text='msg'></p> &l ...

  2. BigDecimal.divide方法

    java.math.BigDecimal.divide(BigDecimal divisor, int roundingMode) 返回一个BigDecimal,其值为(this/除数),其标度是th ...

  3. Java 设计模式之 装饰者模式

    装饰者模式(Decorator Pattern): 概述:装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象 特点: (1) ...

  4. 最长递增子序列nlogn的做法

    费了好大劲写完的  用线段树维护的 nlogn的做法再看了一下 大神们写的 nlogn  额差的好远我写的又多又慢  大神们写的又少又快时间  空间  代码量 哪个都赶不上大佬们的代码 //这是我写的 ...

  5. android sdk 下载 最新版。。4.l

    android sdk 下载 如今时间 2014.0709.,,这是最新的 64 位 windows 的 .为不能翻墙的小伙伴们准本

  6. winform 使用webbrowser 打开不了pdf的解决办法

    最近有个项目需要在winform 打开网络路径的pdf文件,自然想到了webbrowser,但是让我没想到的是,在我电脑调试一点问题都没有,但是到了其他同事的电脑是各种各样的问题,有的打不开,有的显示 ...

  7. visual studio 2013下搭建 安卓,ios,wp app开发平台

    1.安装 visual studio 2013 + Microsoft Visual Studio 2013 Update 4+Microsoft Build Tools 2015 2.安装java ...

  8. [工具]Editplus添加son格式化支持

    EditPlus安装包和json.js文件地址 不喜欢CSDN的积分下载和登录下载,不喜欢百度网盘,就这么倔强 https://github.com/michael-deve/CommonData-E ...

  9. 用sql语句合并工作表

    Sub 工作表合并() f = Application.GetOpenFilename(filefilter:="excel文件,*xlsx", Title:="请选择文 ...

  10. Struts2.xml的配置

    框架初始知识: Servlet  VS   Filter Filter的性能更强,因为Servlet能实现的,Filter都能实现. Filter还有拦截资源的作用 是Servlet所不能实现的. F ...