BZOJ4867 : [Ynoi2017]舌尖上的由乃

首先通过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;
}

  

时间: 2024-07-29 15:50:42

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

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

引子 前些时候,我在群里出了一道题目:将变参的类型连接在一起作为字符串并返回出来,要求只用函数实现,不能借助于结构体实现.用结构体来实现比较简单: template<typename... Args> struct Connect; template< typename First, typename... Rest> struct Connect<First, Rest...> { static string GetName() { return typeid(Fir

舌尖上的安卓(android触控事件机制学习笔记录)

对于一个"我们从来不生产代码,我们只是大自然代码的搬运工"的码农来说.对android的触控机制一直是模棱两可的状态,特别是当要求一些自定义的控件和androide的自带控件(比如ViewPager,ListView,ScrollView)高度嵌套在一起使用时. 花了点时间梳理了下,做个笔记.对于一个触控的事件从用户输入到传递到Actigvity到最外层的Viewgroup在到子View,中间过程还可能穿插多个Viewgroup,android在ViewGroup提供了3个方法来控制流

舌尖上的 Data Miner

谨以此文纪念过去两年的幸福时光~~~ 按下Shift-Alt-s, 这个来到DM最熟练的组合键,不用看跳出的对话框,直接按下Enter键.资深Data Miner提交Job都是这么帅的.Miner一边美滋滋的看着提交Job的圆圈,一圈一圈的转,一边在另一个屏幕上,浏览cnbate.对于上万行代码经验的Miner,他们的Code一般不会在提交30秒以内出现错误,那些语法错误通常是新手才会犯的.Miner的code错误一般会在编译一分钟以后才出现,更高级的是在运行中才会失败.遇到这种bug,Mine

舌尖上的新年

舌尖上的新年 在家过春节,享受着人神共享的美食 ! 有一大桌美食,吃好.喝好.玩儿好,才是硬道理!

舌尖上的程序猿

<舌尖上的程序员> 码完代码,他起身关上电脑,用滚烫的开水为自己泡制一碗腾着热气的老坛酸菜面.中国的程序猿更偏爱拉上窗帘,在黑暗中享受这独特的美食.这是现代工业给一天辛苦劳作的人最好的馈赠.南方一带生长的程序猿尽管在京城多年,但仍口味清淡,他们往往不加料包,由脸颊自然淌下的热泪补充恰当的盐分.他们相信,用这样的方式,可以抹平思考着如今是不是过去想要的未来而带来的大部分忧伤-小宋的父亲在年轻的时候也是从爷爷手里接收了祖传的代码,只是令人吃惊的是,到了小宋这一代,非常多东西都遗失了,可是程序猿苦逼

舌尖上的硬件: 看烤箱里的移动芯片商

1让我们换个地方思考吧,比如说厨房? “ARM.三星.NVIDIA.TSMC,这些厂商都是怎样的角色?”,“三星的猎户座和NVIDIA的Tegra 3都号称基于ARM的Cortex-A9,同样出处的它们为什么看起来却是完全不同的样子,性能也表现各异呢?”,“ARM到底是干什么的?三星又是干什么的?它们之间有着什么关系和联系啊?” 上面这些问题,相信曾经在很多读者的脑海中出现过.ARM是干什么的?三星和NVIDIA又是干什么的?这样的问题虽然并不会影响我们购买手机或者其他半导体产品,但求知欲的作祟

舌尖上的硬件: 厨房中探秘图形渲染

1食物?画卷?食物的画卷 在今后的<舌尖上的硬件>系列当中,我们将会继续保持这样的视角,以各种美味的组合和制作过程来为您展现不同的显卡/半导体芯片技术细节,五味的搭配因何而鲜美诱人.图形处理过程是怎样的精妙.食物为何会让我们大快朵颐.芯片的性能究竟由哪些要素决定.这个世界到底蕴藏了多少和谐与调和的艺术,小小厨房中所发生的一切将会成为我们带您认识电脑世界的载体.最终,我们将会一起探寻.发现并赞美这个世界的本质.如果一路上能够有您相伴,我们感激不尽. 信守承诺,带着一颗探索并感悟世界的心,我们和新

【康康说道】舌尖上的产品

"康康说道"此版块为我公司新开辟的版块,由我公司产品经理杨伟康独家解密医疗软件产品的各种奥秘之处. [杨伟康 简介]1987年生人.2010年开始进入医疗软件行业.2010年在江苏华招网期间进行医药招投标软件的开发:2011年至 今在南京一丹软件有限公司担任项目经理. 产品经理职位,期间负责EMR.CSSD,现接着负责体检软件的发, 开发期间多次与院方前线工作者进行需求对接,开发目标就是把自身作为终端用户.立志将自己负责的项目做到用户满意度最高. <舌尖上的中国>上 说:&

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

一沙一世界,一树一菩提,我们这个世界的深邃全部蕴藏于一个个普通的平凡当中.小小的厨房所容纳的不仅仅是人们对味道的情感,更有推动整个世界前进的动力.要想理解我们的世界,有的时候只需要细细品味一下我们所喜爱的美食即可.正因为此,我们才规划了<舌尖上的硬件>这样一个系列栏目.通过对美食的品味和体会,我们可以更好地理解许多硬件相关的原理.内涵甚至是趣闻,我们所需要为此准备的,其实仅仅是一颗平和的心而已. 在上一期的<舌尖上的硬件>栏目中,我们第一次接触到了隐藏在食物背后的其与半导体业界的神