首先通过DFS序将原问题转化为序列上区间加、询问区间kth的问题。

考虑分块,设块大小为$K$,每块维护排序过后的$pair(值,编号)$。

对于修改,整块的部分可以直接打标记,而零碎的两块因为本来有序,故可以按照修改区间将其分离成两个有序序列$A$(不在修改区间)和$B$(在修改区间)。

对$B$每个值都加上一个常数,再与$A$归并排序,即可在$O(K)$的时间内修改零碎的两块。

对于查询,首先将零碎的两块用同样的方法分离出来,然后二分答案,在每个整块二分查找个数即可,时间复杂度$O(\frac{n}{K}\log^2n)$。

当$K$取$\sqrt{n}\log n$时取得最优复杂度$O(n\sqrt{n}\log n)$。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;
const int N=100010,K=12,M=(N>>K)+5,BUF=6000000;
char Buf[BUF],*buf=Buf;
int n,m,i,lim,op,x,y,g[N],w[N],nxt[N],stq[N],enq[N],dfn;
int block,st[M],en[M],tag[M];P a[N<<1];
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
inline void add(int x,int y,int z){w[y]=z;nxt[y]=g[x];g[x]=y;}
void dfs(int x,int y){
stq[x]=++dfn;
a[dfn]=P(y,dfn);
for(int i=g[x];i;i=nxt[i])dfs(i,y+w[i]);
enq[x]=dfn;
}
inline void change(int o,int l,int r,int p){
static P A[N],B[N];
int ca=0,cb=0,i,j,k=st[o];
for(i=st[o];i<=en[o];i++)if(a[i].second<l||a[i].second>r)A[++ca]=a[i];else B[++cb]=a[i],B[cb].first+=p;
i=j=1;
while(i<=ca&&j<=cb)a[k++]=A[i]<B[j]?A[i++]:B[j++];
while(i<=ca)a[k++]=A[i++];
while(j<=cb)a[k++]=B[j++];
}
inline void modify(int x,int y,int p){
int X=x>>K,Y=y>>K,i;
for(i=X+1;i<Y;i++)tag[i]+=p;
change(X,x,y,p);
if(X<Y)change(Y,x,y,p);
}
inline int ask(int o,int p){
int l=st[o],r=en[o],mid,t=l-1;
if(l>r)return 0;
p-=tag[o];
while(l<=r)if(a[mid=(l+r)>>1].first<=p)l=(t=mid)+1;else r=mid-1;
return t-st[o]+1;
}
inline int kth(int x,int y,int k){
if(k>y-x+1)return -1;
int X=x>>K,Y=y>>K,i,s=n+1,e=n;
tag[block+1]=tag[X];
for(i=st[X];i<=en[X];i++)if(a[i].second>=x&&a[i].second<=y)a[++e]=a[i];
st[block+1]=s,en[block+1]=e;
s=e+1;
if(X<Y){
tag[block+2]=tag[Y];
for(i=st[Y];i<=en[Y];i++)if(a[i].second<=y)a[++e]=a[i];
}
st[block+2]=s,en[block+2]=e;
int l=0,r=lim,mid,t,ans;
while(l<=r){
mid=(l+r)>>1;
t=ask(block+1,mid)+ask(block+2,mid);
for(i=X+1;i<Y&&t<k;i++)t+=ask(i,mid);
if(t>=k)r=(ans=mid)-1;else l=mid+1;
}
return ans;
}
int main(){
fread(Buf,1,BUF,stdin);read(n),read(m),read(x);
for(i=2;i<=n;i++)read(x),read(y),add(x,i,y),lim+=y;
dfs(1,0);
block=n>>K;
for(i=1;i<=n;i++)en[i>>K]=i;
for(i=n;i;i--)st[i>>K]=i;
for(i=0;i<=block;i++)sort(a+st[i],a+en[i]+1);
while(m--){
read(op),read(x),read(y);
if(op==1)printf("%d\n",kth(stq[x],enq[x],y));else modify(stq[x],enq[x],y),lim+=y;
}
return 0;
}

  

BZOJ4867 : [Ynoi2017]舌尖上的由乃的更多相关文章

  1. BZOJ4867 Ynoi2017舌尖上的由乃(dfs序+分块)

    容易想到用dfs序转化为序列上的问题.考虑分块,对每块排序,修改时对于整块打上标记,边界暴力重构排序数组,询问时二分答案,这样k=sqrt(nlogn)时取最优复杂度nsqrt(nlogn)logn, ...

  2. BZOJ_4867_[Ynoi2017]舌尖上的由乃_分块+dfs序

    BZOJ_4867_[Ynoi2017]舌尖上的由乃_分块+dfs序 Description 由乃为了吃到最传统最纯净的美食,决定亲自开垦一片菜园.现有一片空地,由乃已经规划n个地点准备种上蔬菜.最新 ...

  3. (原创)舌尖上的c++--相逢

    引子 前些时候,我在群里出了一道题目:将变参的类型连接在一起作为字符串并返回出来,要求只用函数实现,不能借助于结构体实现.用结构体来实现比较简单: template<typename... Ar ...

  4. 舌尖上的硬件:CPU/GPU芯片制造解析(高清)(组图)

    一沙一世界,一树一菩提,我们这个世界的深邃全部蕴藏于一个个普通的平凡当中.小小的厨房所容纳的不仅仅是人们对味道的情感,更有推动整个世界前进的动力.要想理解我们的世界,有的时候只需要细细品味一下我们所喜 ...

  5. 舌尖上的javascript数组和字符串基本操作

    Javascript数组基本操作 Javascript中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性,索引可能是整数,然而这些数字索引在内部被转换为字符串类型,这是因为javascrip ...

  6. python基础-文件操作

    一.文件操作 打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作. 打开文件的模式有: r ,只读模式[默认模式,文件必须存在,不存在则抛出异 ...

  7. Python之路,Day3 - Python基础3

    一.文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

  8. Python之路第一课Day3--随堂笔记(文件操作)

    一.集合的介绍 1.集合操作 集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变成集合,就自动去重了 关系测试,测试两组数据之前的交集.差集.并集等关系 常用操作 s = se ...

  9. Python之路第一课Day2--随堂笔记

    入门知识拾遗 一.bytes类型 bytes转二进制然后转回来 msg="张杨" print(msg) print(msg.encode("utf-8")) p ...

随机推荐

  1. 页面注册系统--使用forms表单结合ajax

    页面注册系统--使用forms表单结合ajax 在Django中通过forms构建一个表单 1.urls.py 配置路由 from django.conf.urls import url from d ...

  2. nunit单元测试详解

    在粗略看了代码后,下面就详细说明相应的测试标记(属性)的用法. [TestFixture(arguments)]属性标记类为测试类,若没有填写参数,则测试类必须含有无参构造函数,否则需要相应的有参构造 ...

  3. WCF 寄宿Windows以及控制台启动

    一:添加windows服务 二:修改XXXInstaller1的StartType=Automatic,修改ProcessInstaller1的Account=LocalSystem 三:在progr ...

  4. Git和Github入门教程

    一.常用命令 所有命令前都要加 git,如表中的init是指 git init.点击命令可直接跳转至本文第一次使用的地方.以下命令都在命令行里执行. 1.本地命令 行为 命令 备注 初始化 init ...

  5. sed 简单修改配置文件ip地址

    sed -i 's/old ip/new ip/g' file.txt

  6. SQL Server数据库存储过程中拼接字符串注意的问题

    在SQL Server数据库中书写复杂的存储过程时,一般的做法是拼接字符串,最后使用EXEC sp_executesql '拼接的字符串' 查询出结果. 先看一段代码: -- ============ ...

  7. day3.python字符串格式化

    字符串格式化 注意:若在格式化输出中还需要再加%,需要两个%来代替 方法1:%控制格式化输出 例1: print("I'm %s. I'm %d year old" % ('Vam ...

  8. net core体系-web应用程序-4net core2.0大白话带你入门-9asp.net core服务的生命周期

    asp.net core服务的生命周期   Transient:每一次GetService都会创建一个新的实例 Scoped:在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request ...

  9. sql 跨服务器查询

    创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' exec sp_addlinkedsrvlogin ...

  10. PAT (Basic Level) Practise - 成绩排名

    1004. 成绩排名 题目链接:https://www.patest.cn/contests/pat-b-practise/1004 读入n名学生的姓名.学号.成绩,分别输出成绩最高和成绩最低学生的姓 ...