• icpc 2020 澳门 J Jewel Grab (线段树+set)


    题目链接:https://codeforces.com/gym/103119/problem/J

    看到 (k) 只有 (10),所以可以暴力跳段统计答案

    维护每个位置前一个相同颜色出现的位置 (pre[i]),如果 (pre[i] < s),则说明该颜色没有在 (s) 之后出现过,在线段树上二分找到第一个 (pre[x] > s)(x) 即可

    (pre) 的修改要用 (set) 维护一下每个颜色都在哪些位置出现过,修改的时候细心一些,注意不要漏掉 (set, la(某个颜色最后出现的位置))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 200010;
    const int INF = 1000000007;
    
    int n, m;
    ll v[maxn], mvc[maxn]; 
    int c[maxn], pre[maxn], nxt[maxn], la[maxn];
    
    set<int> cp[maxn];
    
    struct Node{
    	int mx;
    	ll sum;
    }t[maxn<<2];
    
    void pushup(int i){
    	t[i].mx = max(t[i<<1].mx, t[i<<1|1].mx); 
    	t[i].sum = t[i<<1].sum + t[i<<1|1].sum;
    }
    
    void build(int i, int l, int r){
    	if(l == r){
    		t[i].mx = pre[l];
    		t[i].sum = v[l];
    		return;
    	}
    	
    	int mid = (l + r) >> 1;
    	build(i << 1, l, mid); build(i << 1 | 1, mid + 1, r);
    	pushup(i); 
    }
    
    void modify(int i, int p, int l, int r){
    	if(l == r){
    		t[i].mx = pre[l];
    		t[i].sum = v[l];
    		return;
    	}
    	
    	int mid = (l + r) >> 1;
    	if(p <= mid) modify(i<<1, p, l, mid);
    	else modify(i<<1|1, p, mid + 1, r);
    	pushup(i);
    }
    
    ll query(int i, int l, int r, int x, int y){
    	if(x <= l && r <= y){
    		return t[i].sum;
    	}
    	int mid = (l + r) >> 1;
    	ll res = 0;
    	if(x <= mid) res += query(i<<1, l, mid, x, y);
    	if(y > mid) res += query(i<<1|1, mid + 1, r, x, y);
    	return res;
    }
    
    int find(int i, int s, int l, int r, int p){ 
    	if(l == r){
    		return l;
    	}
    	
    	int mid = (l + r) >> 1;
    	
    	int pos = -1;
    	if(t[i<<1].mx >= s && p <= mid) pos = find(i<<1, s, l, mid, p); 
    	if(pos != -1) return pos;
    	if(t[i<<1|1].mx >= s) pos = find(i<<1|1, s, mid+1, r, p);
    	return pos;
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	n = read(), m = read();
    	
    	memset(la, -1, sizeof(la));
    	for(int i = 1 ; i <= n ; ++i){
    		c[i] = read(), v[i] = read(); 
    		cp[c[i]].insert(i);
    		pre[i] = la[c[i]];
    		la[c[i]] = i;	
    	} 
    	
    	memset(la, -1, sizeof(la));
    	for(int i = n ; i >= 1 ; --i){
    		nxt[i] = la[c[i]];
    		la[c[i]] = i; 
    	}
    
    	memset(la, -1, sizeof(la));
    	for(int i = 1 ; i <= n ; ++i) la[c[i]] = i;
    	
    	build(1, 1, n);
    
    	int op, k, x, y;
    	for(int i = 1 ; i <= m ; ++i){
    		op = read();
    		if(op == 1) {
    			x = read(), y = read(), k = read();
    			cp[c[x]].erase(x);
    			if(la[c[x]] == x) la[c[x]] = pre[x];
    			v[x] = k;
    			c[x] = y;
    			
    			if(nxt[x] != -1){
    				if(pre[x] != -1){
    					nxt[pre[x]] = nxt[x];
    					pre[nxt[x]] = pre[x];
    					modify(1, nxt[x], 1, n);
    				} else{
    					pre[nxt[x]] = -1;
    					modify(1, nxt[x], 1, n);
    				}
    			} else {
    				if(pre[x] != -1){
    					nxt[pre[x]] = -1;
    				} 
    			}
    			
    			int pos;
    			set<int>::iterator it;
    			it = cp[y].lower_bound(x);
    			if(it == cp[y].end()) {
    				nxt[x] = -1;
    				pre[x] = la[y];
    				if(pre[x] != -1) nxt[pre[x]] = x;
    				modify(1, x, 1, n);
    			}
    			else {
    				pos = *it;
    				if(pre[pos] != -1){
    					nxt[pre[pos]] = x;
    					pre[x] = pre[pos];
    					modify(1, x, 1, n);				
    				} else{
    					pre[x] = -1;
    					modify(1, x, 1, n);
    				}				
    				
    				nxt[x] = pos;
    				pre[pos] = x;
    				modify(1, pos, 1, n);	
    			}
    			
    			cp[y].insert(x);
    			la[y] = max(la[y], x);
    		} else{
    			vector<int> color;
    			color = vector<int>();
    			x = read(), k = read();
    			int cur = x;
    			
    			ll ans = 0;
    			for(int j = 0 ; j <= k && cur <= n ; ++j){
    				int pos = find(1, x, 1, n, cur);
    				if(pos == -1){
    					ans += query(1, 1, n, cur, n);
    					break;
    				}
    				
    				color.push_back(c[pos]);
    				if(j < k) {
    					if(mvc[c[pos]] == 0) mvc[c[pos]] = v[pre[pos]];
    					if(v[pos] > mvc[c[pos]]){
    						ans -= mvc[c[pos]];
    						ans += v[pos];
    						mvc[c[pos]] = v[pos];
    					}	
    				}
    				
    				ans += query(1, 1, n, cur, pos-1);
    				cur = pos + 1;
    			}
    			printf("%lld
    ", ans);
    			
    			for(auto u : color) mvc[u] = 0;
    		}
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    Alink漫谈(五) : 迭代计算和Superstep
    Alink漫谈(四) : 模型的来龙去脉
    Elasticsearch索引模板-转载
    Filebeat配置文件解析-转载
    Logtash 配置文件解析-转载
    Logtash遇到的异常和注意点
    Linux中Sshd服务配置文件优化版本(/etc/ssh/sshd_config)
    运维应急方案撰写-草稿版分享
    du和df的统计结果为什么会不一样?
    全网最详细的Linux命令系列-Screen远程会话命令
  • 原文地址:https://www.cnblogs.com/tuchen/p/15189004.html
Copyright © 2020-2023  润新知