• Codeforces Round #489 (Div. 2) E. Nastya and King-Shamans


    这道题的算法是:
    i从1开始,首先求sum(1-i),然后在[i+1, n]中找到第一个a[j]>=sum(1, i)
    如果a[j]==sum(1, i)结束搜索,否则令i=j,循环过程
    因为每次做完一次之后sum会至少增大一倍,所以一个查询的复杂度会维持到log(Max(a[i]))

    需要维护 区间最大值和区间和 的线段树来实现算法

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    const int N = 2e5+5;
    const int INF = 0x3f3f3f3f;
    typedef long long ll;
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    
    int n, q;
    int A[N];
    int maxx[N << 2];
    ll sum[N << 2];
    void Build(int l, int r, int rt) {
    	if(l == r) {
    		sum[rt] = A[l];
    		maxx[rt] = A[l];
    		return;
    	}
    	int m = (l + r) >> 1;
    	Build(lson);
    	Build(rson);
    	sum[rt] = sum[rt << 1] + sum[rt << 1|1];
    	maxx[rt] = max(maxx[rt << 1], maxx[rt << 1 | 1]);
    }
    void Update(int pos, int num, int l, int r, int rt) {
    	if(l == r) {
    		sum[rt] = num;
    		maxx[rt] = num;
    		return;
    	}
    	int m = (l + r) >> 1;
    	if(pos <= m) Update(pos, num, lson);
    	else Update(pos, num, rson);
    	sum[rt] = sum[rt << 1] + sum[rt << 1|1];
    	maxx[rt] = max(maxx[rt << 1], maxx[rt << 1 | 1]);
    }
    ll Sum(int L, int R, int l, int r, int rt) {
    	if(L <= l && r <= R) {
    		return sum[rt];
    	}
    	int m = (l + r) >> 1;
    	ll ret = 0;
    	if(L <= m) ret += Sum(L, R, lson);
    	if(R > m) ret += Sum(L, R, rson);
    	return ret;
    }
    
    pair<ll, int> Ans;
    void Find(int L, int R, ll num, int l, int r, int rt) {
    	if(l == r) {
    		Ans = make_pair(maxx[rt], l);
    		return;
    	} 
    	int m = (l + r) >> 1;
    	if(maxx[rt << 1] >= num && L <= m) Find(L, R, num, lson);
    	if(maxx[rt<<1|1] >= num && R > m && Ans.first == -1) Find(L, R, num, rson);
    }
    int main() {
    	while(~scanf("%d %d", &n, &q)) {
    		for(int i = 1; i <= n; ++i) {
    			scanf("%d", &A[i]);
    		}
    		Build(1 , n, 1);
    	//	printf("%lld
    ", Sum(1, 2, 1, n, 1));
    		for(int i = 0; i < q; ++i) {
    			int a, b; scanf("%d %d", &a, &b);
    			Update(a, b, 1, n, 1);
    			A[a] = b;
    			if(A[1] == 0) printf("1
    ");
    			else if(A[1] == A[2]) printf("2
    ");
    			else {
    				int pre = 2;
    				while(1) {
    					ll tmpTarget = Sum(1, pre, 1, n, 1);
    					if(tmpTarget > maxx[1]) {
    						printf("-1
    ");
    						break;
    					}
    					Ans = make_pair(-1, -1);
    					Find(pre+1, n, tmpTarget, 1, n, 1);
    					if(Ans.first == -1) {
    						printf("-1
    ");
    						break;
    					}
    					ll nowTarget = Sum(1, Ans.second-1, 1, n, 1);
    					if(Ans.first == nowTarget) {
    						printf("%d
    ", Ans.second);
    						break;
    					} else {
    						pre = Ans.second;
    					}
    						
    				}
    			}
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    UGUI ScrollView 自适应高度
    OnApplicationFocus 与 OnApplicationPause
    unity读取二进制配置文件
    sprite实现影子
    protobuf 标签DataFormat =DataFormat.FixedSize解决连续int字段无法解析
    unity显示网络延迟ping
    ios piv6遭拒绝
    读取FTP上的某个文本文档内容到本地
    EF提交插入数据catch捕获具体异常方法
    ASP.NET后台调用API 方法 POST方式
  • 原文地址:https://www.cnblogs.com/Basasuya/p/9236397.html
Copyright © 2020-2023  润新知