bzoj4867: [Ynoi2017]舌尖上的由乃
没得去冬令营的菜鸡只能在机房刷题耍子咯
这道题需要平衡块的大小,好像thuwc d1t1就考了
先分块,设块的大小为k,每一块块内排序,复杂度O(nlogk)
修改完整块打标记,不完整暴力,复杂度O(n/k+k)
询问二分答案,整块再二分位置,不完整的暴力拿出来,也二分,复杂度O(logn*n/k*logk+k)
明显最后一个比较大,可以让logn*n/k*logk=k,这样会比较平衡
logk约等于logn,于是块的大小设为sqrt(n)*logn
实测k=sqrt(n),询问强的要跑25s+,弱的1s
k=sqrt(n)*logn就都是5s了
分块细节非常多啊。。。。。。码量也很大
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const int maxn=110000; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void write(int d) { if(d<0){putchar('-');d=-d;} if(d>=10)write(d/10); putchar(d%10+'0'); } struct node { int x,y,d,next; }a[maxn*2];int len,last[maxn]; inline void ins(int x,int y,int d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=last[x];last[x]=len; } struct point{int d,id;}p[maxn];int plen; inline bool cmp(point p1,point p2){return p1.d==p2.d?p1.id<p2.id:p1.d<p2.d;} int L[maxn],R[maxn]; void dfs(int x) { int now=++plen; p[now].id=plen; L[x]=plen; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; p[plen+1].d=p[now].d+a[k].d; dfs(y); } R[x]=plen; } //-------------------------------------------init------------------------------------------------------ int n,block,st[maxn],ad[maxn]; int op,x,k; int Lli,Rli; inline int be(int tt){return (tt-1)*block+1;} inline bool inin(int i){return (L[x]<=p[i].id&&p[i].id<=R[x]);} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ point t1[maxn],t2[maxn];int t1len,t2len; inline void mergesort(int u) { int i=1,j=1,o=be(u); while(i<=t1len&&j<=t2len) if(cmp(t1[i],t2[j]))p[o++]=t1[i++]; else p[o++]=t2[j++]; while(i<=t1len)p[o++]=t1[i++]; while(j<=t2len)p[o++]=t2[j++]; } inline void bl_change(int u) { Lli=be(u),Rli=min(be(u+1)-1,n); t1len=0;t2len=0; for(int i=Lli;i<=Rli;i++) if(inin(i))p[i].d+=k,t1[++t1len]=p[i]; else t2[++t2len]=p[i]; mergesort(u); } //~~~~~~~~~~~~change~~~~~~~~~~~~~~~~~~~~ inline int bl_findkth(int u) { Lli=be(u),Rli=min(be(u+1)-1,n); for(int i=Lli;i<=Rli;i++) if(inin(i)) { k--; if(k==0)return p[i].d+ad[u]; } } inline bool check(int D,int u,int v) { int ret=0; int l,r,num; l=1,r=t1len,num=0; while(l<=r){ int mid=(l+r)/2; if(D>=t1[mid].d+ad[u])l=mid+1,num=mid; else r=mid-1; } ret+=num; l=1,r=t2len,num=0; while(l<=r){ int mid=(l+r)/2; if(D>=t2[mid].d+ad[v])l=mid+1,num=mid; else r=mid-1; } ret+=num; if(ret>=k)return true; for(int i=u+1;i<v;i++) { int l=be(i),r=min(be(i+1)-1,n),num=l-1; while(l<=r) { int mid=(l+r)/2; if(D>=p[mid].d+ad[i])l=mid+1,num=mid; else r=mid-1; } ret+=num-be(i)+1; if(ret>=k)return true; } return false; } //~~~~~~~~~~~~~getans~~~~~~~~~~~~~~~~~~~~ //-----------------------------------------------solve-------------------------------------------------------- int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int Q,F,dd; n=read(),Q=read(),read(); for(int i=2;i<=n;i++) F=read(),dd=read(),ins(F,i,dd); dfs(1); block=int(sqrt(double(n+1))*log(n)/log(2)); int h=1; for(int i=1;i<=n;i++) { st[i]=(i-1)/block+1; if(i!=1&&st[i]!=st[i-1]) sort(p+h,p+i,cmp),h=i; } sort(p+h,p+n+1,cmp); while(Q--) { op=read(),x=read(),k=read(); if(op==2) { int u=st[L[x]],v=st[R[x]]; if(u==v)bl_change(u); else { bl_change(u),bl_change(v); for(int i=u+1;i<v;i++)ad[i]+=k; } } else { if(R[x]-L[x]+1<k){puts("-1");continue;} int u=st[L[x]],v=st[R[x]]; if(u==v)write(bl_findkth(u)),puts(""); else { t1len=0; Lli=be(u),Rli=min(be(u+1)-1,n); for(int i=Lli;i<=Rli;i++) if(inin(i))t1[++t1len]=p[i]; t2len=0; Lli=be(v),Rli=min(be(v+1)-1,n); for(int i=Lli;i<=Rli;i++) if(inin(i))t2[++t2len]=p[i]; int l=1,r=1e7,ans; while(l<=r) { int mid=(l+r)/2; if(check(mid,u,v))r=mid-1,ans=mid; else l=mid+1; } write(ans);puts(""); } } } return 0; }
pain and happy in the cruel world.