zoukankan      html  css  js  c++  java
  • loj6046 「雅礼集训 2017 Day8」爷

    https://loj.ac/problem/6046

    最近遇到几个分块题,我发现我一遇到分块题就死活构造不出来

    不对,明明是,遇到数据结构题,就死活构造不出来。

    所以我就找了几个分块题做做。

    其实分块,树上的,很多都是先求一个dfs序,或者树剖,用一个log的代价或者没有多余的代价变成序列上的东西

    树上的东西想到dfs序和树剖不是套路么……

    很多不好维护的东西,都可以用分块来做,诶这不是我以前说过的么。

    这道题,如果分块,那么按照套路,块内就可以排序,我们可以二分一个答案,然后在块内二分。

    算了算复杂度,2个log,一个根号,不是很优秀的样子。

    而题面上说$k leq 10$,肯定有阴谋!

    我们想,如果一个块内,元素最小最大值之差不大,我们就可以直接开个数组记录前缀和就好了,少一个log呢。

    于是我们就,每次块内大小$>sz$或者最小值最大值之差$>S$,我们就新开一个块。

    然后每隔一段时间重新分一下块,这样就非常优秀啦。

    一开始自己智障,把$S$设得有点大,T掉了。

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<set>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
    const int maxn=2e5+7,maxt=1000+7,maxs=2e4+7,S=2e3,INF=0x3f3f3f3f;
    int n,m,len,a[maxn],bel[maxn],sz;
    int L[maxn],R[maxn];
    
    char cc;ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int fir[maxn],nxt[maxn],to[maxn],e=0,v[maxn];
    void add(int x,int y,int z) {
    	to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
    }
    
    int dfn[maxn],fed[maxn],dfn_clock;
    void dfs(int pos,int d) {
    	dfn[pos]=++dfn_clock;
    	a[dfn_clock]=d;
    	for(int y=fir[pos];y;y=nxt[y]) dfs(to[y],d+v[y]);
    	fed[pos]=dfn_clock;
    }
    
    int sum[maxt][maxs],pl[maxt],pr[maxt],tot;
    int d[maxn];
    
    inline void pd(int x) {
    	if(!d[x]) return;
    	For(i,L[x],R[x]) a[i]+=d[x];
    	d[x]=0;
    }
    
    inline void ud(int x) {
    	pl[x]=INF; pr[x]=-INF;
    	For(j,L[x],R[x]) {
    		pl[x]=min(pl[x],a[j]);
    		pr[x]=max(pr[x],a[j]);
    	}
    	For(j,0,pr[x]-pl[x]) sum[x][j]=0;
    	For(j,L[x],R[x]) ++sum[x][a[j]-pl[x]];
    	For(j,1,pr[x]-pl[x]) sum[x][j]+=sum[x][j-1];
    }
    
    void bld() {
    	For(i,1,tot) pd(i);
    	int now=1,ld=INF,rd=-INF; L[1]=1;
    	For(i,1,n) {
    		ld=min(ld,a[i]); rd=max(rd,a[i]);
    		if(rd-ld>S||i-L[now]>=sz) {
    			R[now]=i-1;
    			L[++now]=i;
    			ld=rd=a[i];
    		}
    		R[bel[i]=now]=i;
    	}
    	tot=now;
    	For(i,1,tot) ud(i);
    }
    
    inline int get_sum(int p,int x) {
    	if(x<pl[p]) return 0;
    	if(x>pr[p]) return sum[p][pr[p]-pl[p]];
    	return sum[p][x-pl[p]];
    }
    
    inline int q(int ld,int rd,int x) {
    	int rs=0,lt=bel[ld],rt=bel[rd];
    	if(lt==rt) {
    		For(i,ld,rd) if(a[i]<=x) ++rs;
    		return rs;
    	}
    	if(ld!=L[lt]) {For(i,ld,R[lt]) if(a[i]<=x) ++rs;}
    	else rs+=get_sum(lt,x);
    	if(rd!=R[rt]) {For(i,L[rt],rd) if(a[i]<=x) ++rs;}
    	else rs+=get_sum(rt,x);
    	For(i,lt+1,rt-1) rs+=get_sum(i,x);
    	return rs;
    }
    
    inline int Yth(int ld,int rd,int k) {
    	int lt=bel[ld],rt=bel[rd];
    	pd(lt); pd(rt);
    	if(rd-ld+1<k) return -1;
    	int l=INF,r=-INF,mid;
    	For(i,lt,rt) l=min(l,pl[i]),r=max(r,pr[i]);
    	if(l==r) return l; --l;
    	while(l<r-1) {
    		mid=(l+r)>>1;
    		if(q(ld,rd,mid)>=k) r=mid;
    		else l=mid;
    	}
    	return r;
    }
    
    inline void chge(int ld,int rd,int x) {
    	int lt=bel[ld],rt=bel[rd];
    	if(lt==rt) {
    		pd(lt); For(i,ld,rd) a[i]+=x; ud(lt);
    		return;
    	}
    	if(ld!=L[lt]) {
    		pd(lt); For(i,ld,R[lt]) a[i]+=x; ud(lt);
    	}
    	else d[lt]+=x,pl[lt]+=x,pr[lt]+=x;
    	if(rd!=R[rt]) {
    		pd(rt); For(i,L[rt],rd) a[i]+=x; ud(rt);
    	}
    	else d[rt]+=x,pl[rt]+=x,pr[rt]+=x;
    	For(i,lt+1,rt-1) d[i]+=x,pl[i]+=x,pr[i]+=x;
    }
    
    int main() {
    	read(n); read(m); read(len); sz=300;
    	int op,x,y;
    	For(i,2,n) {
    		read(x); read(y);
    		add(x,i,y);
    	}
    	dfs(1,0);
    	bld();
    	For(i,1,m) {
    		read(op); read(x); read(y);
    		if(op==1) printf("%d
    ",Yth(dfn[x],fed[x],y));
    		else chge(dfn[x],fed[x],y);
    		if(i%1000==0) bld();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    各种素材类精品网站
    Java如何设置代理ip
    Spring事务的实现方式和原理以及隔离级别?
    Spring 是什么?
    线程池中阻塞队列的作用?为什么是先添加队列而不是先创建最大线程?
    为什么用线程池?解释下线程池参数
    并发三大特性
    ThreadLocal的原理和使用场景。
    谈谈对线程安全的理解
    sleep,wait,join,yield
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/9210673.html
Copyright © 2011-2022 走看看