其他分享
首页 > 其他分享> > bzoj4867: [Ynoi2017]舌尖上的由乃

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;
}

 

标签:ch,bzoj4867,int,mid,len,Ynoi2017,舌尖,num,include
来源: https://www.cnblogs.com/AKCqhzdy/p/10301822.html