zoukankan      html  css  js  c++  java
  • BZOJ4867 : [Ynoi2017]舌尖上的由乃

    首先通过DFS序将原问题转化为序列上区间加、询问区间kth的问题。

    考虑分块,设块大小为$K$,每块维护排序过后的$pair(值,编号)$。

    对于修改,整块的部分可以直接打标记,而零碎的两块因为本来有序,故可以按照修改区间将其分离成两个有序序列$A$(不在修改区间)和$B$(在修改区间)。

    对$B$每个值都加上一个常数,再与$A$归并排序,即可在$O(K)$的时间内修改零碎的两块。

    对于查询,首先将零碎的两块用同样的方法分离出来,然后二分答案,在每个整块二分查找个数即可,时间复杂度$O(frac{n}{K}log^2n)$。

    当$K$取$sqrt{n}log n$时取得最优复杂度$O(nsqrt{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
    ",kth(stq[x],enq[x],y));else modify(stq[x],enq[x],y),lim+=y;
      }
      return 0;
    }
    

      

  • 相关阅读:
    Java微信二次开发(八)
    Java微信二次开发(七)
    Java微信二次开发(六)
    Java微信二次开发(五)
    Java微信二次开发(四)
    Java微信二次开发(三)
    IIS中X509Certificate遇见的问题
    SQL Server 数据库定时自动备份
    ASP.NET 5 (vNext) 理解和概述
    ASP.NET 5 (vNext) Linux部署
  • 原文地址:https://www.cnblogs.com/clrs97/p/7416252.html
Copyright © 2011-2022 走看看