zoukankan      html  css  js  c++  java
  • [Codeforces 1199D]Welfare State(线段树)

    [Codeforces 1199D]Welfare State(线段树)

    题面

    给出一个长度为n的序列,有q次操作,操作有2种

    1.单点修改,把(a_x)修改成y

    2.区间修改,把序列中值<v的数全部修改成v

    问q次操作后的序列

    分析

    主要考虑如何实现操作2,可以通过有条件的下推标记来实现。线段树的叶子节点存储序列的值,上推的时候维护区间最小值。如果给某个节点下推标记的时候发现该节点对于的区间最小值>v,则不下推(最小值>v,即所有数都>v,不用会产生修改),否则把区间中的最小值和v取max.

    单点修改的时候先下推标记,然后跟普通线段树一样修改即可。

    代码

    #include<iostream>
    #include<cstdio>
    #define maxn 200000
    using namespace std;
    int n;
    int a[maxn+5];
    int q;
    struct segment_tree{
    	struct node{
    		int l;
    		int r;
    		int mark;
    		int v;
    	}tree[maxn*4+5];
    	void push_up(int pos){
    		tree[pos].v=min(tree[pos<<1].v,tree[pos<<1|1].v);
    	}
    	void build(int l,int r,int pos){
    		tree[pos].l=l;
    		tree[pos].r=r;
    		tree[pos].mark=-1;
    		if(l==r){
    			tree[pos].v=a[l];
    			return;
    		}
    		int mid=(l+r)>>1;
    		build(l,mid,pos<<1);
    		build(mid+1,r,pos<<1|1);
    		push_up(pos);
    	}
    	void push_down(int pos){
    		if(tree[pos].mark!=-1){
                //只有当前值比它大才下推
    			if(tree[pos].mark>tree[pos<<1].mark||tree[pos<<1].mark==-1) tree[pos<<1].mark=tree[pos].mark;
    			if(tree[pos].mark>tree[pos<<1].v) tree[pos<<1].v=tree[pos].mark;
    			if(tree[pos].mark>tree[pos<<1|1].mark||tree[pos<<1|1].mark==-1) tree[pos<<1|1].mark=tree[pos].mark;
    			if(tree[pos].mark>tree[pos<<1|1].v) tree[pos<<1|1].v=tree[pos].mark;
    			tree[pos].mark=-1;
    		}
    	}
    	void update_segment(int L,int R,int pt,int pos){
    		if(L<=tree[pos].l&&R>=tree[pos].r){
    			if(tree[pos].v<=pt){
    				tree[pos].v=pt;
    				tree[pos].mark=pt;
    			}
    			return;
    		}
    		push_down(pos);
    		int mid=(tree[pos].l+tree[pos].r)>>1;
    		if(L<=mid) update_segment(L,R,pt,pos<<1);
    		if(R>mid) update_segment(L,R,pt,pos<<1|1);
    		push_up(pos);
    	}
    	void update_point(int tpos,int val,int pos){
    		if(tree[pos].l==tree[pos].r){
    			tree[pos].v=val;
    			return;
    		}
    		push_down(pos);
    		int mid=(tree[pos].l+tree[pos].r)>>1;
    		if(tpos<=mid) update_point(tpos,val,pos<<1);
    		else update_point(tpos,val,pos<<1|1);
    		push_up(pos); 
    	}
    	int query(int tpos,int pos){
    		if(tree[pos].l==tree[pos].r){
    			return tree[pos].v;
    		}
    		push_down(pos);
    		int mid=(tree[pos].l+tree[pos].r)>>1;
    		if(tpos<=mid) return query(tpos,pos<<1);
    		else return query(tpos,pos<<1|1);
    	}
    }T;
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	scanf("%d",&q);
    	int cmd,x,v;
    	T.build(1,n,1);
    	for(int i=1;i<=q;i++){
    		scanf("%d",&cmd);
    		if(cmd==1){
    			scanf("%d %d",&x,&v);
    			T.update_point(x,v,1);
    		}else{
    			scanf("%d",&v);
    			T.update_segment(1,n,v,1);
    		}
    	}
    	for(int i=1;i<=n;i++){
    		printf("%d ",T.query(i,1));
    	}
    }
    
    
  • 相关阅读:
    solr
    2.配置Flutter代码编辑器(IDE)
    1.Flutter的下载安装和环境配置
    ReactNative开发环境配置,新手踩坑必备.我也是新手
    汉字转拼音,获取汉字首字母
    For循环性能优化
    JavaScript滑块简易取色器
    C# 获取汉字拼音首字母(修正X问题,真正修正)
    团队项目-个人博客5.31
    团队项目-个人博客5.30
  • 原文地址:https://www.cnblogs.com/birchtree/p/11273817.html
Copyright © 2011-2022 走看看