令人抓狂的整体二分题。根本原因还是我太菜了。

在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了……不过还是太慢。

题目传送门:洛谷P4175

题意简述:

一棵 \(n\) 个结点的树,每个点有点权。

有 \(m\) 次操作,每个操作要么是更改单点点权,要么是查询树链上第 \(k\) 大点权。

题解:

树套树固然可以,但是整体二分也很好。

整体二分就是对于所有的询问一起二分答案,在二分区间范围内的查询和修改一并下传。

这题把整体二分基础题的操作搬到了链上,但是实现方法并没有太大不同。

初始点权看成增加点权,插入在所有操作的最前面即可。

更改点权可以看成删除点权再增加点权,变成两次修改即可。

这题整体二分要求第 \(k\) 大,考虑二分出的答案 \(mid\),将大于 \(mid\) 的修改转成单点权值 \(\pm 1\),

而对于树链查询第 \(k\) 大,则转化成链上权值之和是否等于 \(k\)。

写整体二分题永远要注意二分的条件,我的条件是,链上大于 \(mid\) 的点数小于 \(k\) 个则答案小于等于 \(mid\),否则答案大于 \(mid\)。

单点修改,树链查询要是还用树剖就太naive了,套路转化:

考虑每个节点维护到根的路径上的信息,那么单点修改就变成子树修改,链查就变成四个单点查了(需要求LCA)。

而子树是一个区间,区间加法,单点查询;再使用树状数组差分技巧转化成单点差分,区间前缀和。

注意到还要求LCA,直接在DFS的时候用Tarjan处理就好了。

关于判断无解:当然可以直接处理掉……不过这样就必须求树链长度了。

我的方法是,往权值里面加一个-1,如果答案是-1,则真实答案应该是无解。

我的代码还离散化了权值,其实没用……

其他恶心的地方就是整体二分基本功了,太弱了调了好久……注意循环变量是指向真实操作的下标的指针还是真实操作的下标,如果你写结构体当我没说。

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. using namespace std;
  5. const int MN=80005;
  6. const int MM=110005;
  7. const int MQ=140005;
  8. int n,m,q,w[MN],d[MQ],c;
  9. int o[MQ],a[MQ],b[MQ],p[MQ],lc[MQ],ans[MQ];
  10. int eh[MN],qh[MN],nxt[MM*2],to[MM*2],tot;
  11. inline void ins(int*h,int x,int y){nxt[++tot]=h[x],to[tot]=y,h[x]=tot;}
  12. int ld[MN],rd[MN],faz[MN],dfc;
  13. int fa[MN];int ff(int x){return fa[x]?fa[x]=ff(fa[x]):x;}
  14. void dfs(int u,int f){
  15. faz[u]=f,ld[u]=++dfc;
  16. for(int i=eh[u];i;i=nxt[i])if(to[i]!=f)dfs(to[i],u),fa[to[i]]=u;
  17. for(int i=qh[u];i;i=nxt[i])if(lc[to[i]])lc[to[i]]=ff(lc[to[i]]);else lc[to[i]]=u;
  18. rd[u]=dfc;
  19. }
  20. int B[MN];
  21. inline void I(int i,int x){for(;i<=n;i+=i&-i)B[i]+=x;}
  22. inline int Q(int i){int a=0;for(;i;i-=i&-i)a+=B[i];return a;}
  23. int t[MQ];
  24. void s(int l,int r,int L,int R){
  25. if(l>r)return;
  26. if(L==R){for(int i=l;i<=r;++i)ans[p[i]]=L;return;}
  27. int m=L+R>>1,p1=l-1,p2=r+1;
  28. for(int j=l,i;j<=r;++j){
  29. if(o[i=p[j]]>0){
  30. int x=Q(ld[a[i]])+Q(ld[b[i]])-Q(ld[lc[i]])-Q(ld[faz[lc[i]]]);
  31. if(x<o[i])o[i]-=x,t[++p1]=i;
  32. else t[--p2]=i;
  33. }
  34. else if(b[i]>m){
  35. I(ld[a[i]],o[i]?-1:1),I(rd[a[i]]+1,o[i]?1:-1);
  36. t[--p2]=i;
  37. }
  38. else t[++p1]=i;
  39. }
  40. for(int i=l;i<=r;++i)if(o[p[i]]<=0&&b[p[i]]>m)I(ld[a[p[i]]],o[p[i]]?1:-1),I(rd[a[p[i]]]+1,o[p[i]]?-1:1);
  41. reverse(t+p2,t+r+1),memcpy(p+l,t+l,r-l+1<<2);
  42. s(l,p1,L,m),s(p2,r,m+1,R);
  43. }
  44. int main(){
  45. scanf("%d%d",&n,&m);
  46. for(int i=1;i<=n;++i)scanf("%d",&w[i]),o[++q]=0,a[q]=i,b[q]=w[i],p[q]=q;
  47. for(int i=1,x,y;i<n;++i)scanf("%d%d",&x,&y),ins(eh,x,y),ins(eh,y,x);
  48. for(int i=1;i<=m;++i){
  49. ++q,scanf("%d%d%d",&o[q],&a[q],&b[q]),p[q]=q;
  50. if(!o[q])o[++q]=-1,a[q]=a[q-1],b[q]=w[a[q-1]],p[q]=q,w[a[q-1]]=b[q-1];
  51. }
  52. for(int i=1;i<=q;++i)if(o[i]>0)ins(qh,a[i],i),ins(qh,b[i],i);else d[++c]=b[i];
  53. d[++c]=-1;sort(d+1,d+c+1);c=unique(d+1,d+c+1)-d-1;
  54. for(int i=1;i<=q;++i)if(o[i]<=0)b[i]=lower_bound(d+1,d+c+1,b[i])-d;
  55. dfs(1,0),s(1,q,1,c);
  56. for(int i=1;i<=q;++i)if(o[i]>0)ans[i]==1?puts("invalid request!"):printf("%d\n",d[ans[i]]);
  57. return 0;
  58. }
  59. // 20:08 - 21:03

洛谷 P4175: bzoj 1146: [CTSC2008]网络管理的更多相关文章

  1. BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[Submi ...

  2. BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 870  Solved: 299[Submit] ...

  3. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  4. 洛谷 P4298: bzoj 1143: [CTSC2008]祭祀

    题目传送门:洛谷 P4298. 题意简述: 给定一个 \(n\) 个点,\(m\) 条边的简单有向无环图(DAG),求出它的最长反链,并构造方案. 最长反链:一张有向无环图的最长反链为一个集合 \(S ...

  5. bzoj 1146 [CTSC2008]网络管理Network

    很久之前写过 count on the tree. 然后一直不懂树状数组是怎么套上这个主席树的. 看了两小时发现它套的就是个权值线段树, 看不出来可持久化在哪里. 因为动态开点所以空间nlog2n. ...

  6. BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序

    Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路 ...

  7. [BZOJ 1146] [CTSC2008]网络管理Network(树状数组+主席树)

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  8. 洛谷 P4175 [CTSC2008]网络管理 解题报告

    P4175 [CTSC2008]网络管理 题目描述 带修改树上链的第\(k\)大 输入输出格式 输入格式: 第一行为两个整数\(N\)和\(Q\),分别表示路由器总数和询问的总数. 第二行有\(N\) ...

  9. 洛谷P4175 - [CTSC2008]网络管理

    Portal Description 给出一棵\(n(n\leq8\times10^4)\)个点的带点权的树,进行\(m(m\leq8\times10^4)\)次操作,操作有两种: 修改一个点的点权. ...

随机推荐

  1. codeforces 1041 E.Vasya and Good Sequences(暴力?)

    E. Vasya and Good Sequences time limit per test 2 seconds memory limit per test 256 megabytes input ...

  2. 记一次java程序out of memory问题

    在一个比较大批量的pdf转String项目中遇到了:java.lang.OutOfMemoryError: Java heap space错误 第一反应肯定是程序没有写好,大量循环时没有把程序中没有用 ...

  3. vs2017自动生成的#include“stdafx.h”详解及解决方案

    vs2017自动生成的#include“stdafx.h”详解及解决方案 问题描述: 在高版本的Visual Studio的默认设置中,会出现这么一个现象,在新建项目之后,项目会自动生成#includ ...

  4. 【刷题】BZOJ 3262 [HNOI2008]GT考试

    Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字. 他的不吉利数学A1A2...Am(0< ...

  5. [USACO12NOV]同时平衡线Concurrently Balanced Strings DP map 思维

    题面 [USACO12NOV]同时平衡线Concurrently Balanced Strings 题解 考虑DP. \(f[i]\)表示以\(i\)为左端点的合法区间个数.令\(pos[i]\)表示 ...

  6. 【BZOJ1864】三色二叉树(动态规划)

    [BZOJ1864]三色二叉树(动态规划) 题面 BZOJ 题解 首先把树给构出来. 设\(f[i][0/1]\)表示当前节点\(i\),是否是绿色节点的子树中最大/最小的绿色节点的个数和. 转移很显 ...

  7. 洛谷 P4091 [HEOI2016/TJOI2016]求和 解题报告

    P4091 [HEOI2016/TJOI2016]求和 题目描述 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: \[ f(n)=\sum_{i=0}^n\ ...

  8. 第一章:CDib类库的建立

    VC++图像处理程序设计(第1版)    杨淑莹 编著     边奠英 主审 第一章 位图基础 Joanna-In-Hdu&Hust 手工打,印象更深刻 使用工具 VS2010 mfc  整本 ...

  9. C 语法中static 和inline联合使用

    最近在学习阶段,翻阅代码.发现有一个用法比较让我奇怪,就上网查了一下 ? 1 static inline void somefunction(void); 这里是举例说明,这行代码是放在.h文件中的. ...

  10. Android Intent 总结

    //打开指定网页Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse("http://www.goo ...