博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 4867 分块+神tm卡常
阅读量:5155 次
发布时间:2019-06-13

本文共 2955 字,大约阅读时间需要 9 分钟。

思路:

注意到len<=10

按照权值max-min<=sqrt(n)*len 分块
记一下前缀和  每修改sqrt(n)次以后重新分块
 
修改的时候整块打标记  两边重构
(这题常数卡得要死   找同学要来fread才过)

 查询的时候 就 二分答案 O(sqrt(n))判断

二分的上界要实时根据maxdeep变化才能过

 

//By SiriusRen#include
using namespace std;const int N=100050;int n,m,op,xx,yy,len,limval,Block,deep[N],cnt,dfn[N],lst[N],maxdep;int first[N],next[N],v[N],w[N],tot,a[N],pos[N],maxx[N],minn[N],L[N],R[N],tag[N];unsigned short sum[1200][33333];inline int nextChr() { static const int siz=1<<22; static char buf[siz],*chr=buf+siz; if(chr==buf+siz)fread(chr=buf,1,siz,stdin); return int(*chr++);}inline int read(){ register int r=0,c=nextChr(); for(;c<48;c=nextChr()); for(;c>47;c=nextChr())r=(r<<3)+(r<<1)+c-48; return r;}inline void add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}void dfs(int x){ dfn[x]=++cnt,a[cnt]=deep[x]; for(int i=first[x];~i;i=next[i]) deep[v[i]]=deep[x]+w[i],dfs(v[i]); lst[x]=cnt;}void rebuild(int x){ for(int i=0;i<=limval;i++)sum[x][i]=0;maxx[x]=0; for(int i=L[x];i<=R[x];i++)sum[x][a[i]]++,maxx[x]=max(maxx[x],a[i]); for(int i=1;i<=maxx[x];i++)sum[x][i]+=sum[x][i-1];}void build(){ int bs=0;limval=n*len/Block;maxdep=0; for(int i=1;i<=n;i++)a[i]=a[i]+tag[pos[i]],maxdep=max(maxdep,a[i]); for(int i=1;i<=n;){ bs++,L[bs]=R[bs]=i,maxx[bs]=minn[bs]=a[i]; while(i<=n&&max(maxx[bs],a[i])-min(minn[bs],a[i])<=limval&&R[bs]-L[bs]<=Block) R[bs]=i,pos[i]=bs,maxx[bs]=max(maxx[bs],a[i]),minn[bs]=min(minn[bs],a[i]),i++; } for(int i=1;i<=bs;i++){ maxx[i]-=(tag[i]=minn[i]); for(int j=L[i];j<=R[i];j++)a[j]-=tag[i]; rebuild(i); }}void change(int l,int r,int wei){ if(pos[l]==pos[r]){
for(int i=l;i<=r;i++)a[i]+=wei;rebuild(pos[l]);} else{ for(int i=l;i<=R[pos[l]];i++)a[i]+=wei;rebuild(pos[l]); for(int i=L[pos[r]];i<=r;i++)a[i]+=wei;rebuild(pos[r]); for(int i=pos[l]+1;i<=pos[r]-1;i++)tag[i]+=wei; }}int kth(int l,int r,int wei){ int ans=0; if(pos[l]==pos[r]){
for(int i=l;i<=r;i++)ans+=(tag[pos[l]]+a[i]<=wei);} else{ for(int i=l;i<=R[pos[l]];i++)ans+=(tag[pos[l]]+a[i]<=wei); for(int i=L[pos[r]];i<=r;i++)ans+=(tag[pos[r]]+a[i]<=wei); for(int i=pos[l]+1;i<=pos[r]-1;i++)if(wei>=tag[i]) ans+=sum[i][min(maxx[i],wei-tag[i])]; }return ans;}int bsrch(int l,int r,int k){ if(r-l+1
>1; if(kth(l,r,mid-1)+1<=k)lft=mid+1,ans=mid; else rit=mid-1; }return ans;}int main(){ memset(first,-1,sizeof(first)); n=read(),m=read(),len=read(),Block=min(n,(int)sqrt(n)); for(int i=2;i<=n;i++)xx=read(),yy=read(),add(xx,i,yy); dfs(1),build(); while(m--){ if(cnt>Block)cnt=0,build(); op=read(),xx=read(),yy=read(); if(op==1)printf("%d\n",bsrch(dfn[xx],lst[xx],yy)); else limval+=yy,maxdep+=yy,change(dfn[xx],lst[xx],yy),cnt++; }}

 

转载于:https://www.cnblogs.com/SiriusRen/p/6767835.html

你可能感兴趣的文章
利用SignalR来同步更新Winfrom
查看>>
反射机制
查看>>
CocoaPod
查看>>
BZOJ 1251: 序列终结者 [splay]
查看>>
5G边缘网络虚拟化的利器:vCPE和SD-WAN
查看>>
MATLAB基础入门笔记
查看>>
【UVA】434-Matty&#39;s Blocks
查看>>
Android开发技术周报 Issue#80
查看>>
hadoop2.2.0+hive-0.10.0完全分布式安装方法
查看>>
django知识点总结
查看>>
C++ STL stack、queue和vector的使用
查看>>
使用Reporting Services时遇到的小问题
查看>>
约瑟夫问题
查看>>
Arduino 报错总结
查看>>
树莓派Android Things物联网开发:树莓派GPIO引脚图
查看>>
矩阵快速幂---BestCoder Round#8 1002
查看>>
js兼容公用方法
查看>>
如何将应用完美迁移至Android P版本
查看>>
【转】清空mysql一个库中的所有表的数据
查看>>
基于wxPython的python代码统计工具
查看>>