• NowCoder IOI 周赛 26 [提高组]


    C - 未曾设想的道路

    解法

    对于没有 (0) 操作

    可以用线段树维护区间 (k) 大值。当然,你还可以做一个关于 “下标” 和 ”数字“ 的前缀和然后暴枚数字。

    对于 (0) 操作时 (l=r)

    树套树!

    外层维护下标,内层维护数字。因为每次只增加一个数字,所以插入是两个 $log $ 的。查询再套个二分就是三个 (log)

    对于 (100\%) 的数据

    借用上文一个比较靠谱的思路,我们尝试在有 (0) 操作的情况下维护区间 (k) 大值。

    既然修改那么就涉及懒标记的问题,我们需要维护区间 (k) 大懒标记来维护区间 (k) 大值。为了维护区间 (k) 大懒标记还需要记录当前懒标记。

    完了吗?

    事实上,我们并不能直接用区间 (k) 大懒标记来更新区间 (k) 大值。因为根据题目中数字的构造方法,懒标记必须是连续的(也即从第一个 (0) 操作开始的累积),而区间 (k) 大值可能并没有添加区间 (k) 大懒标记之前的某些懒标记,这样构造出来的区间 (k) 大值就是不合法的。

    所以我们还需要维护当前区间 (k) 大值(也即使用了每一次 (0) 操作的数字中的 (k) 大值)。

    再讲一下区间 (k) 大懒标记与当前区间 (k) 大值如何合并(令它们分别为 (a[],b[]))。

    先在优先队列中加入 (a_i+b_1),然后每次找到最大值 (a_i+b_j) 就加入 (a_i+b_{j+1})。正确性比较显然,时间复杂度 (mathcal O(klog k))

    总时间复杂度 (mathcal O(nklog n+mklog nlog k))

    同机房的巨巨用分块爆踩本做法,下次一定去看看。

    代码

    大常数竟是我自己。

    #pragma GCC optimize(2)
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    #define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
    #define print(x,y) write(x),putchar(y) 
    
    template <class T> inline T read(const T sample) {
        T x=0; int f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    template <class T> inline void write(const T x) {
        if(x<0) return (void) (putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
    
    typedef pair <int,int> pii;
    
    const int maxn=1e5+5,inf=1e9;
    
    int n,m,h[maxn],tmp[105],ans[105];
    struct node {
    	int laz,la[105],cur[105],mx[105];
    	
    	node() {
    		rep(i,0,100) la[i]=cur[i]=mx[i]=-inf;
    	}
    } t[maxn<<2];
    priority_queue <pii> q;
    
    void Merge(int *a,int *b) {
    	static int c[105],i,j; i=1,j=1;
    	rep(k,1,100)
    		if(a[i]>b[j]) c[k]=a[i++];
    		else c[k]=b[j++];
    	memcpy(a,c,sizeof c);
    }
    
    void pushUp(int o) {
    	memcpy(t[o].cur,t[o<<1].cur,sizeof t[o<<1].cur),Merge(t[o].cur,t[o<<1|1].cur);
    	memcpy(t[o].mx,t[o<<1].mx,sizeof t[o<<1].mx),Merge(t[o].mx,t[o<<1|1].mx);
    }
    
    void Unite(int *a,int *b) {
    	static int dep[105];
    	while(!q.empty()) q.pop();
    	rep(i,1,100) q.push(make_pair(a[i]+b[1],i)),dep[i]=1;
    	rep(i,1,100) {
    		pii t=q.top(); q.pop();
    		tmp[i]=Max(-inf,t.first);
    		q.push(make_pair(a[t.second]+b[++dep[t.second]],t.second));
    	}
    }
    
    void pushDown(int o) {
    	if(t[o].la[1]>-1e8) { 
    		rep(i,1,100) tmp[i]=t[o<<1].laz+t[o].la[i];
    		Merge(t[o<<1].la,tmp);
    		rep(i,1,100) tmp[i]=t[o<<1|1].laz+t[o].la[i];
    		Merge(t[o<<1|1].la,tmp);
    		
    		t[o<<1].laz+=t[o].laz,t[o<<1|1].laz+=t[o].laz;
    		
    		Unite(t[o].la,t[o<<1].cur),Merge(t[o<<1].mx,tmp);
    		Unite(t[o].la,t[o<<1|1].cur),Merge(t[o<<1|1].mx,tmp);
    		
    		rep(i,1,100) t[o<<1].cur[i]+=t[o].laz,t[o<<1|1].cur[i]+=t[o].laz;
    		rep(i,1,100) t[o].la[i]=-inf;
    		t[o].laz=0;
    	}
    }
    
    void build(int o,int l,int r) {
    	if(l==r) return (void)(t[o].cur[1]=t[o].mx[1]=h[l]);
    	int mid=l+r>>1;
    	build(o<<1,l,mid),build(o<<1|1,mid+1,r);
    	pushUp(o);
    }
    
    void Modify(int o,int l,int r,int L,int R,int k) {
    	if(l>R || r<L) return;
    	if(l>=L && r<=R) {
    		t[o].laz+=k,tmp[1]=t[o].laz;
    		rep(i,1,100) t[o].cur[i]+=k;
    		rep(i,2,100) tmp[i]=-inf;
    		Merge(t[o].la,tmp),Merge(t[o].mx,t[o].cur);
    		return;
    	}
    	int mid=l+r>>1;
    	pushDown(o);
    	Modify(o<<1,l,mid,L,R,k),Modify(o<<1|1,mid+1,r,L,R,k);
    	pushUp(o);
    }
    
    void Query(int o,int l,int r,int L,int R) {
    	if(l>R || r<L) return;
    	if(l>=L && r<=R) return (void)(Merge(ans,t[o].mx));
    	int mid=l+r>>1;
    	pushDown(o);
    	Query(o<<1,l,mid,L,R),Query(o<<1|1,mid+1,r,L,R);
    }
    
    int main() {
    	n=read(9),m=read(9);
    	rep(i,1,n) h[i]=read(9);
    	build(1,1,n);
    	while(m--) {
    		int op=read(9),l=read(9),r=read(9),x=read(9);
    		if(!op) Modify(1,1,n,l,r,x);
    		else {
    			rep(i,1,100) ans[i]=-inf;
    			Query(1,1,n,l,r);
    			int res;
    			rep(i,1,x) if(ans[i]>-1e8) res=ans[i];
    			print(res,'
    ');
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    python3----列表
    python3----字符串
    PTA 深入虎穴 (正解)和树的同构
    第5章 树与二叉树学习小结
    第4章学习小结_串(BF&KMP算法)、数组(三元组)
    《数据结构》第3章-栈与队列的学习总结
    《数据结构》第2章线性表的学习总结
    Web安全基础——小白自学
    git撤销commit
    收藏一些比较好的前端博客
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/14880630.html
Copyright © 2020-2023  润新知