zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    HDU 4024 Dwarven Sniper’s hunting(数学公式 或者是二分)
    二分图最大匹配总结
    HDU 4022 Bombing (STL应用)
    HDU 1847 Good Luck in CET4 Everybody!(组合博弈)
    HDU 1556 Color the ball(树状数组)
    HDU 4023 Game(博弈)
    HDU 1406 完数(水题)
    HDU 4021 24 Puzzle
    Oracle 多表查询优化
    【编程之美】字符串移位包含的问题(续)
  • 原文地址:https://www.cnblogs.com/Gloid/p/10011543.html
Copyright © 2011-2022 走看看