• 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;
    }
  • 相关阅读:
    sql server 2008数据复制方法
    排错技能:任务管理器中追踪某w3wp.exe是哪个IIS站点的application pool
    SplendidCRM中给来自EditView中的listbox控件设置选中值或数据源
    jQuery String Functions
    [转]jquery getJSON 数据联动(采用序列化和反序列化获取数据) .
    [转]javascript eval函数解析json数据时为什加上圆括号eval("("+data+")")
    深入理解C语言
    Qt回忆录之配置开发环境
    360电话面试
    浅谈C++设计模式之单例模式
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10301822.html
Copyright © 2020-2023  润新知