• BZOJ4867 Ynoi2017舌尖上的由乃(dfs序+分块)


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

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 100010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,len,p[N],deep[N],dfn[N],id[N],size[N],t,cnt,s;
    int block,num,pos[N],L[N],R[N],lazy[N];
    struct data{int to,nxt,len;
    }edge[N];
    struct data2
    {
        int i,x;
        bool operator <(const data2&a) const
        {
            return x<a.x;
        }
    }a[N],u[N],v[N],w[N];
    struct data3{int i,j,x,op;}Q[N];
    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;}
    void dfs(int k)
    {
        size[k]=1;dfn[k]=++cnt;id[cnt]=k;s=max(s,deep[k]);
        for (int i=p[k];i;i=edge[i].nxt)
        {
            deep[edge[i].to]=deep[k]+edge[i].len;
            dfs(edge[i].to);
            size[k]+=size[edge[i].to];
        }
    }
    void add(int k,int l,int r,int x)
    {
        int n=0,m=0;
        for (int i=L[k];i<=R[k];i++)
        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;
        else v[++m]=a[i];
        int p=1,q=1;
        for (int i=L[k];i<=R[k];i++)
        if (u[p].x<v[q].x&&p<=n||q>m) a[i]=u[p++];
        else a[i]=v[q++];
    }
    int calc(int k,int l,int r)
    {
        if (pos[l]==pos[r])
        {
            int s=0;
            for (int i=l;i<=r;i++)
            if (deep[id[i]]+lazy[pos[l]]<=k) s++;
            return s;
        }
        else
        {
            int s=0;
            for (int i=pos[l]+1;i<pos[r];i++)
            s+=upper_bound(a+L[i],a+R[i]+1,(data2){0,k-lazy[i]})-a-L[i];
            for (int i=l;i<=R[pos[l]];i++)
            if (deep[id[i]]+lazy[pos[l]]<=k) s++;
            for (int i=L[pos[r]];i<=r;i++)
            if (deep[id[i]]+lazy[pos[r]]<=k) s++;
            return s;
        }
    }
    double complexity(double k,double q){return (m-q)*(n/k+3*k)+q*log(s+(m-q)*(len+1>>1))/log(2)*(n/k*log(n)/log(2)+k);}
    namespace segmenttree
    {
        int L[N<<2],R[N<<2],tree[N<<2],lazy[N<<2];
        void build(int k,int l,int r)
        {
            L[k]=l,R[k]=r,lazy[k]=0;
            if (l==r) {tree[k]=deep[id[l]];return;}
            int mid=l+r>>1;
            build(k<<1,l,mid);
            build(k<<1|1,mid+1,r);
            tree[k]=max(tree[k<<1],tree[k<<1|1]);
        }
        void update(int k,int x){tree[k]+=x,lazy[k]+=x;}
        void down(int k){update(k<<1,lazy[k]),update(k<<1|1,lazy[k]),lazy[k]=0;}
        void add(int k,int l,int r,int x)
        {
            if (L[k]==l&&R[k]==r) {update(k,x);return;}
            if (lazy[k]) down(k);
            int mid=L[k]+R[k]>>1;
            if (r<=mid) add(k<<1,l,r,x);
            else if (l>mid) add(k<<1|1,l,r,x);
            else add(k<<1,l,mid,x),add(k<<1|1,mid+1,r,x);
            tree[k]=max(tree[k<<1],tree[k<<1|1]);
        }
        int query(int k,int l,int r)
        {
            if (L[k]==l&&R[k]==r) return tree[k];
            if (lazy[k]) down(k);
            int mid=L[k]+R[k]>>1;
            if (r<=mid) return query(k<<1,l,r);
            else if (l>mid) return query(k<<1|1,l,r);
            else return max(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4867.in","r",stdin);
        freopen("bzoj4867.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();len=read();
        for (int i=2;i<=n;i++)
        {
            int x=read(),y=read();
            addedge(x,i,y);
        }
        dfs(1);segmenttree::build(1,1,n);
        int qwq=0;
        for (int i=1;i<=m;i++)
        {
            int op=read(),k=read(),x=read();
            if (op==1) qwq++;
            Q[i].op=op,Q[i].i=dfn[k],Q[i].j=dfn[k]+size[k]-1,Q[i].x=x;
        }
        block=1;for (int i=2;i<=n;i++) if (complexity(i,qwq)<complexity(block,qwq)) block=i;
        num=(n-1)/block+1;
        for (int i=1;i<=num;i++)
        {
            L[i]=(i-1)*block+1,R[i]=min(n,i*block);
            for (int j=L[i];j<=R[i];j++)
            pos[j]=i,a[j].i=j,a[j].x=deep[id[j]];
            sort(a+L[i],a+R[i]+1);
        }
        for (int i=1;i<=m;i++)
        {
            int l=Q[i].i,r=Q[i].j,x=Q[i].x;
            if (Q[i].op==1)
            {
                int left=1,right=segmenttree::query(1,l,r),ans=-1;
                while (left<=right)
                {
                    int mid=left+right>>1;
                    if (calc(mid,l,r)>=x) ans=mid,right=mid-1;
                    else left=mid+1;
                }
                printf("%d
    ",ans);
            }
            else
            {
                segmenttree::add(1,l,r,x);
                if (pos[l]==pos[r]) add(pos[l],l,r,x);
                else
                {
                    for (int i=pos[l]+1;i<pos[r];i++) lazy[i]+=x;
                    add(pos[l],l,R[pos[l]],x),add(pos[r],L[pos[r]],r,x);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    在Unity3D中开发的Hologram Shader
    在Unity3D中开发的Toon Shader
    在Unity3D中开发的Dissolve Shader
    2017.2.26
    2017.2.21
    2017.2.20
    2017.2.19
    2017.2.18
    2017.2.17<转>
    2017.2.16 linux
  • 原文地址:https://www.cnblogs.com/Gloid/p/10011543.html
Copyright © 2020-2023  润新知