• [BJOI2019] 删数



    题解

    题目的含义可以看做是以权值为下标的一些柱子,每个柱子的高度就是这个权值的出现的次数,然后把这些柱子向左推倒,一个高度为(h)的柱子的影响范围为(i-h+1sim i)
    然后答案就是查询(1sim n)的这段区间没有被覆盖的点的个数
    这个东西可以用线段树来维护
    就是维护区间的最小值以及区间最小值的个数
    对于整个序列的操作
    就相当于把值域的查询范围左移或者右移
    左移右移的时候要加上新的贡献,减去已经不在范围的贡献
    然后由于我写的不知道为啥一直74分就直接抄了个题解

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    # define ls (now << 1)
    # define rs (now << 1 | 1)
    const int M = 600005 ;
    using namespace std ;
    
    inline int read() {
    	char c = getchar() ; int x = 0 , w = 1 ;
    	while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    	while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    	return x*w ;
    }
    
    int val[M] , cnt[M] ;
    int n , m , lp , rp , upp , Np , dlt ;
    struct Node { 
    	int tag , tmi , cnt ;
    	Node () { } ;
    } t[M * 4] ;
    inline Node pushup(Node lt , Node rt) {
    	Node p ; p.tag = 0 ; p.cnt = 0 ;
    	p.tmi = min( lt.tmi , rt.tmi ) ;
    	if(lt.tmi == p.tmi) p.cnt += lt.cnt ;
    	if(rt.tmi == p.tmi) p.cnt += rt.cnt ;
    	return p ;
    }
    inline void update(int now , int k) {
    	t[now].tmi += k ;  
    	t[now].tag += k ;
    }
    inline void pushdown(int now) {
    	if(t[now].tag) {
    		update(ls , t[now].tag) ; 
    		update(rs , t[now].tag) ;
    		t[now].tag = 0 ;
    	}
    }
    void build(int l , int r , int now) {
    	t[now].tag = t[now].tmi = 0 ; t[now].cnt = r - l + 1 ;
    	if(l == r) return ; int mid = (l + r) >> 1; 
    	build(l , mid , ls) ; build(mid + 1 , r , rs) ;
    }
    void Change(int L , int R , int k , int l , int r , int now) {
    	if(l > R || r < L) return ;
    	if(l >= L && r <= R) { 
    		update(now , k) ; 
    		return ; 
    	}
    	pushdown(now) ; int mid = (l + r) >> 1 ;
    	if(mid >= R) Change(L , R , k , l , mid , ls) ;
    	else if(mid < L) Change(L , R , k , mid + 1 , r , rs) ;
    	else Change(L , mid , k , l , mid , ls) , Change(mid + 1 , R , k , mid + 1 , r , rs) ;
    	t[now] = pushup(t[ls] , t[rs]) ;
    }
    Node query(int L , int R , int l , int r , int now) {
    	if(l >= L && r <= R) return t[now] ;
    	pushdown(now) ; int mid = (l + r) >> 1 ;
    	if(mid >= R) return query(L , R , l , mid , ls) ;
    	else if(mid < L) return query(L , R , mid + 1 , r , rs) ;
    	else return pushup(query(L , mid , l , mid , ls) , query(mid + 1 , R , mid + 1 , r , rs)) ;
    }
    
    inline void CP(int x , int w) {
    	int k = cnt[Np + x] + (w > 0) ; cnt[Np + x] += w ;
    	if(x <= n) Change(Np + x - k + 1 , Np + x - k + 1 , w , 1 , upp , 1) ;
    }
    int main() {
    	n = read() ; m = read() ; 
    	upp = (n + m) * 2 + 1 ; Np = n + m ; build(1 , upp , 1) ;
    	for(int i = 1 ; i <= n ; i ++) {
    		val[i] = read() ;
    		CP(val[i] , 1) ;
    	}
    	int pos , x ;
    	while(m --) {
    		pos = read() ; x = read() ;
    		if(pos > 0) {
    			CP(val[pos] + dlt , -1) ;
    			val[pos] = x - dlt ;
    			CP(val[pos] + dlt , 1) ;
    		}
    		else {
    			if(x > 0) {
    				-- Np ; ++ dlt ;
    				int posi = Np + n + 1 ;
    				if(cnt[posi] > 0)
    					Change(posi - cnt[posi] + 1 , posi , -1 , 1 , upp , 1) ;
    			}
    			else {
    				int posi = Np + n + 1 ; 
    				++ Np ; -- dlt ;
    				if(cnt[posi] > 0) 
    					Change(posi - cnt[posi] + 1 , posi , 1 , 1 , upp , 1) ;
    			}
    		}
    		Node tmp = query(Np + 1 , Np + n , 1 , upp , 1) ;
    		printf("%d
    ",tmp.tmi ? 0 : tmp.cnt) ;
    	}
    	return 0 ;
    }
    
  • 相关阅读:
    跨域资源共享 CORS 详解
    C# 每月第一天和最后一天
    jexus http to https
    ASP.NET MVC 路由学习
    jexus
    centos7 添加开机启动项
    jexus docker
    HTTP2.0新特性
    jexus配置支持Owin
    Autofac Named命名和Key Service服务
  • 原文地址:https://www.cnblogs.com/beretty/p/10759197.html
Copyright © 2020-2023  润新知