[Ynoi2017]舌尖上的由乃

Description

维护区间加和区间第k小。
n<=100000

Solution

分块,设块大小为k相信大家都会O(n/k log^2 n)的查询和O(k)的修改。
什么你不会O(k)的修改?归并啊归并啊。
那么平衡规划一下k= nlogn
总复杂度 O(nnlogn)

Code

#include 
#include 
#include 
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,a) for(int i=lst[a];i;i=nxt[i])
using namespace std;

int read() {
    char ch;
    for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
    int x=ch-'0';
    for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    return x;
}

void write(int x) {
    if (!x) {puts("0");return;}
    if (x<0) {putchar('-');x=-x;}
    char ch[20];int tot=0;
    for(;x;x/=10) ch[++tot]=x%10+'0';
    fd(i,tot,1) putchar(ch[i]);
    puts("");
}

const int N=5*1e5+5,M=100;

int t[N],val[N],nxt[N],lst[N],num;

void add(int x,int y,int z) {
    t[++num]=y;val[num]=z;nxt[num]=lst[x];lst[x]=num;
}

struct P{int v,w;}a[N],b[N],c[N];
bool cmp(P x,P y) {return x.v<y.v;}

int dfn[N],size[N],tot,n,m;

void dfs(int x,int y,int z) {
    dfn[x]=++tot;a[tot].v=z;a[tot].w=tot;size[x]=1;
    rep(i,x) if (t[i]!=y) {dfs(t[i],x,z+val[i]);size[x]+=size[t[i]];}
}

int bl[N],L[N],R[N],lazy[N],Sz;

int find(int w) {fo(i,1,Sz) if (L[i]<=w&&w<=R[i]) return i;}

int p[N],q[N];
bool bz[N];

void rebuild(int v,int l,int r,int k) {
    fo(i,L[v],R[v]) bz[i]=0;
    fo(i,l,r) a[i].v+=k,bz[a[i].w]=1;

    q[0]=p[0]=0;
    fo(i,L[v],R[v]) 
        if (bz[i]) q[++q[0]]=i;
        else p[++p[0]]=i;

    int i=1,j=1,cnt=0;
    while (i<=q[0]&&j<=p[0]) {
        if (b[q[i]].v+kq[i++]];c[cnt].v+=k;}
        else c[++cnt]=b[p[j++]];
    }
    while (i<=q[0]) {c[++cnt]=b[q[i++]];c[cnt].v+=k;}
    while (j<=p[0]) c[++cnt]=b[p[j++]];

    fo(i,1,cnt) b[L[v]+i-1]=c[i];
    fo(i,L[v],R[v]) a[b[i].w].w=i;
}

int len,opt,x,k,z,l,r,u,v;

int solve(int u,int l,int r,int v) {
    int cnt=0;
    fo(i,l,r) if (a[i].v+lazy[u]<=v) cnt++;
    return cnt;
}

int query(int u,int v) {
    int l=L[u],r=R[u]+1;
    while (lint mid=l+r>>1;
        if (b[mid].v+lazy[u]<=v) l=mid+1;
        else r=mid;
    }
    return l-L[u];
}

int check(int mid) {
    int res=0;
    if (u==v) return solve(u,l,r,mid);
    res=solve(u,l,R[u],mid)+solve(v,L[v],r,mid);
    fo(i,u+1,v-1) res+=query(i,mid);
    return res;
}

int main() {
    //freopen("yuno.in","r",stdin);
    //freopen("yuno.out","w",stdout);
    n=read();m=read();len=read();
    fo(i,2,n) {
        x=read();z=read();
        add(x,i,z);
    }
    dfs(1,0,0);

    fo(i,1,n) bl[i]=(i-1)/M+1;Sz=bl[n];
    fo(i,1,Sz) L[i]=R[i-1]+1,R[i]=min(L[i]+M-1,n);
    fo(i,1,Sz) {
        fo(j,L[i],R[i]) b[j]=a[j];
        sort(b+L[i],b+R[i]+1,cmp);
        fo(j,L[i],R[i]) a[b[j].w].w=j;
    }

    for(;m;m--) {
        opt=read();x=read();k=read();
        l=dfn[x];r=dfn[x]+size[x]-1;
        u=find(l);v=find(r);
        if (opt==1) {
            if (k>size[x]) {write(-1);continue;}
            int le=0,ri=(n+m)*10;
            while (leint mid=le+ri>>1;
                if (check(mid)>=k) ri=mid;
                else le=mid+1;
            }
            write(le);
        } else {
            if (u==v) {rebuild(u,l,r,k);continue;}
            fo(i,u+1,v-1) lazy[i]+=k;
            rebuild(u,l,R[u],k);rebuild(v,L[v],r,k);
        }
    }

    return 0;
}

UPD:找到错了,原来是我本来开了一个全局变量结果却手贱int了它
然后我TLE了,由乃题日常结局

你可能感兴趣的:(分块)