容易想到用dfs序转化为序列上的问题。考虑分块,对每块排序,修改时对于整块打上标记,边界暴力重构排序数组,询问时二分答案,这样k=sqrt(nlogn)时取最优复杂度nsqrt(nlogn)logn,离跑过去还差一点。二分答案这一部分看上去很难优化,考虑重构时不那么暴力,将要修改的和不要修改的部分分别从已排序数组中提出来,归并即可,这样k=sqrt(n)logn时取最优复杂度nsqrt(n)logn。尽管加了一些奇怪的卡常然而并没有什么卵用,bzoj上根本过不掉。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. #define ll long long
  9. #define N 100010
  10. char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
  11. int gcd(int n,int m){return m==?n:gcd(m,n%m);}
  12. int read()
  13. {
  14. int x=,f=;char c=getchar();
  15. while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
  16. while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
  17. return x*f;
  18. }
  19. int n,m,len,p[N],deep[N],dfn[N],id[N],size[N],t,cnt,s;
  20. int block,num,pos[N],L[N],R[N],lazy[N];
  21. struct data{int to,nxt,len;
  22. }edge[N];
  23. struct data2
  24. {
  25. int i,x;
  26. bool operator <(const data2&a) const
  27. {
  28. return x<a.x;
  29. }
  30. }a[N],u[N],v[N],w[N];
  31. struct data3{int i,j,x,op;}Q[N];
  32. void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
  33. void dfs(int k)
  34. {
  35. size[k]=;dfn[k]=++cnt;id[cnt]=k;s=max(s,deep[k]);
  36. for (int i=p[k];i;i=edge[i].nxt)
  37. {
  38. deep[edge[i].to]=deep[k]+edge[i].len;
  39. dfs(edge[i].to);
  40. size[k]+=size[edge[i].to];
  41. }
  42. }
  43. void add(int k,int l,int r,int x)
  44. {
  45. int n=,m=;
  46. for (int i=L[k];i<=R[k];i++)
  47. if (a[i].i>=l&&a[i].i<=r) u[++n].i=a[i].i,deep[id[a[i].i]]+=x,u[n].x=a[i].x+x;
  48. else v[++m]=a[i];
  49. int p=,q=;
  50. for (int i=L[k];i<=R[k];i++)
  51. if (u[p].x<v[q].x&&p<=n||q>m) a[i]=u[p++];
  52. else a[i]=v[q++];
  53. }
  54. int calc(int k,int l,int r)
  55. {
  56. if (pos[l]==pos[r])
  57. {
  58. int s=;
  59. for (int i=l;i<=r;i++)
  60. if (deep[id[i]]+lazy[pos[l]]<=k) s++;
  61. return s;
  62. }
  63. else
  64. {
  65. int s=;
  66. for (int i=pos[l]+;i<pos[r];i++)
  67. s+=upper_bound(a+L[i],a+R[i]+,(data2){,k-lazy[i]})-a-L[i];
  68. for (int i=l;i<=R[pos[l]];i++)
  69. if (deep[id[i]]+lazy[pos[l]]<=k) s++;
  70. for (int i=L[pos[r]];i<=r;i++)
  71. if (deep[id[i]]+lazy[pos[r]]<=k) s++;
  72. return s;
  73. }
  74. }
  75. double complexity(double k,double q){return (m-q)*(n/k+*k)+q*log(s+(m-q)*(len+>>))/log()*(n/k*log(n)/log()+k);}
  76. namespace segmenttree
  77. {
  78. int L[N<<],R[N<<],tree[N<<],lazy[N<<];
  79. void build(int k,int l,int r)
  80. {
  81. L[k]=l,R[k]=r,lazy[k]=;
  82. if (l==r) {tree[k]=deep[id[l]];return;}
  83. int mid=l+r>>;
  84. build(k<<,l,mid);
  85. build(k<<|,mid+,r);
  86. tree[k]=max(tree[k<<],tree[k<<|]);
  87. }
  88. void update(int k,int x){tree[k]+=x,lazy[k]+=x;}
  89. void down(int k){update(k<<,lazy[k]),update(k<<|,lazy[k]),lazy[k]=;}
  90. void add(int k,int l,int r,int x)
  91. {
  92. if (L[k]==l&&R[k]==r) {update(k,x);return;}
  93. if (lazy[k]) down(k);
  94. int mid=L[k]+R[k]>>;
  95. if (r<=mid) add(k<<,l,r,x);
  96. else if (l>mid) add(k<<|,l,r,x);
  97. else add(k<<,l,mid,x),add(k<<|,mid+,r,x);
  98. tree[k]=max(tree[k<<],tree[k<<|]);
  99. }
  100. int query(int k,int l,int r)
  101. {
  102. if (L[k]==l&&R[k]==r) return tree[k];
  103. if (lazy[k]) down(k);
  104. int mid=L[k]+R[k]>>;
  105. if (r<=mid) return query(k<<,l,r);
  106. else if (l>mid) return query(k<<|,l,r);
  107. else return max(query(k<<,l,mid),query(k<<|,mid+,r));
  108. }
  109. }
  110. int main()
  111. {
  112. #ifndef ONLINE_JUDGE
  113. freopen("bzoj4867.in","r",stdin);
  114. freopen("bzoj4867.out","w",stdout);
  115. const char LL[]="%I64d\n";
  116. #else
  117. const char LL[]="%lld\n";
  118. #endif
  119. n=read(),m=read();len=read();
  120. for (int i=;i<=n;i++)
  121. {
  122. int x=read(),y=read();
  123. addedge(x,i,y);
  124. }
  125. dfs();segmenttree::build(,,n);
  126. int qwq=;
  127. for (int i=;i<=m;i++)
  128. {
  129. int op=read(),k=read(),x=read();
  130. if (op==) qwq++;
  131. Q[i].op=op,Q[i].i=dfn[k],Q[i].j=dfn[k]+size[k]-,Q[i].x=x;
  132. }
  133. block=;for (int i=;i<=n;i++) if (complexity(i,qwq)<complexity(block,qwq)) block=i;
  134. num=(n-)/block+;
  135. for (int i=;i<=num;i++)
  136. {
  137. L[i]=(i-)*block+,R[i]=min(n,i*block);
  138. for (int j=L[i];j<=R[i];j++)
  139. pos[j]=i,a[j].i=j,a[j].x=deep[id[j]];
  140. sort(a+L[i],a+R[i]+);
  141. }
  142. for (int i=;i<=m;i++)
  143. {
  144. int l=Q[i].i,r=Q[i].j,x=Q[i].x;
  145. if (Q[i].op==)
  146. {
  147. int left=,right=segmenttree::query(,l,r),ans=-;
  148. while (left<=right)
  149. {
  150. int mid=left+right>>;
  151. if (calc(mid,l,r)>=x) ans=mid,right=mid-;
  152. else left=mid+;
  153. }
  154. printf("%d\n",ans);
  155. }
  156. else
  157. {
  158. segmenttree::add(,l,r,x);
  159. if (pos[l]==pos[r]) add(pos[l],l,r,x);
  160. else
  161. {
  162. for (int i=pos[l]+;i<pos[r];i++) lazy[i]+=x;
  163. add(pos[l],l,R[pos[l]],x),add(pos[r],L[pos[r]],r,x);
  164. }
  165. }
  166. }
  167. return ;
  168. }

BZOJ4867 Ynoi2017舌尖上的由乃(dfs序+分块)的更多相关文章

  1. BZOJ4867 : [Ynoi2017]舌尖上的由乃

    首先通过DFS序将原问题转化为序列上区间加.询问区间kth的问题. 考虑分块,设块大小为$K$,每块维护排序过后的$pair(值,编号)$. 对于修改,整块的部分可以直接打标记,而零碎的两块因为本来有 ...

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

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

  3. bzoj 4765 普通计算姬 dfs序 + 分块

    题目链接 Description "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些.普通计算机能计算数列区间和,而普通计算姬能 ...

  4. 2016 ACM/ICPC Asia Regional Dalian Online 1010 Weak Pair dfs序+分块

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submissio ...

  5. 【HDU4366】【DFS序+分块】Successor

    Problem Description Sean owns a company and he is the BOSS.The other Staff has one Superior.every st ...

  6. HDU 4366 Successor(dfs序 + 分块)题解

    题意:每个人都有一个上司,每个人都有能力值和忠诚值,0是老板,现在给出m个询问,每次询问给出一个x,要求你找到x的所有直系和非直系下属中能力比他高的最忠诚的人是谁 思路:因为树上查询很麻烦,所以我们直 ...

  7. BZOJ 4765 普通计算姬 dfs序+分块+树状数组+好题!!!

    真是道好题...感到灵魂的升华... 按dfs序建树状数组,拿前缀和去求解散块: 按点的标号分块,分成一个个区间,记录区间子树和 的 总和... 具体地,需要记录每个点u修改后,对每一个块i的贡献,记 ...

  8. HDU - 4366 Successor DFS序 + 分块暴力 or 线段树维护

    给定一颗树,每个节点都有忠诚和能力两个参数,随意指定一个节点,要求在它的子树中找一个节点代替它,这个节点要满足能力值大于它,而且是忠诚度最高的那个. 首先,dfs一下,处理出L[i], R[i]表示d ...

  9. HDU4366 Successor【dfs序 分块】

    HDU4366 Successor 题意: 给出一棵根为\(1\)的树,每个点有两个权值\(x,y\),每次询问一个点的子树中\(x\)比这个点的\(x\)大且\(y\)值最大的那个点 题解: 如果以 ...

随机推荐

  1. 北京Uber优步司机奖励政策(3月3日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. 全球订单最多的成都优步推出"南北通勤线"业务

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. 一种精准monkey测试的方法

    WeTest 导读 相信大家都知道移动端应用的monkey测试吧,不知你们有没有为monkey测试的太过于随机性的特性有过困扰,至少在我们这种界面控件较少且控件位置较偏的app的使用上其测试有效性大打 ...

  4. Ubuntu主题美化篇

    主题美化篇 Ubuntu自带的主题简直不敢恭维,这里博主将它美化了一番,心情瞬间都好了一大截,码代码也会飞起!!先放一张我美化后的效果. 桌面和终端效果如下: unity-tweak-tool 调整 ...

  5. 「日常训练」湫湫系列故事——设计风景线(HDU-4514)

    题意与分析 中文题目,木得题意的讲解谢谢. 然后还是分解成两个任务:a)判环,b)找最长边. 对于这样一个无向图,强行转换成负权然后bellman-ford算法求最短是难以实现的,所以感谢没有环--我 ...

  6. redmine本地安装部署

    1.railsinstaller-3.2.0.exe 下载地址 http://railsinstaller.org/en 安装railsinstaller  一直点next就可以了,安装完成之后C盘会 ...

  7. Selenium(Python)PageObject页面对象

    使用PageObject页面对象的好处是, 当页面元素的位置发生改变时, 只需要去修改Xpath或者ID, 而不用去修改测试用例本身: 本次的思路是: 1.常用方法类 2.页面对象类 3.测试用例类 ...

  8. Linux命令应用大词典-第25章 备份与还原

    25.1 mkisofs:创建ISO9660/Joliet/hfs文件系统

  9. Unity与服务区交互数据

    Unity与服务区交互数据 Unity可能在用的时候使用到登陆等需要与服务器交互数据.今天尝试使用了WWW类和WWWForm类来实现Get请求与Post请求. 1.WWW Unity圣典解释: WWW ...

  10. 【聚合报告】- 秒懂jmeter