ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study (线段树+思维)

Ryuji doesn’t want to study

这个题挺有意思的
两棵线段树
一棵维护的是数组
另一棵维护的是数组每一项乘以它的倒着的位数
如下图:
一棵维护的是矩形
另一颗维护的是大的三角形
在这里插入图片描述

AC code
/*
Ryuji doesn't want to study
ACM-ICPC 2018 徐州赛区网络预赛 H.
https://nanti.jisuanke.com/t/A2007
题面:多组询问 [l, r]  a[l] * L + a[l+1] * (L-1) + …… + a[r-1] * 2 + a[r] 以及 单点修改
解法:两棵线段树
一颗维护num[i]
另一颗维护num[i]*(n-i+1)
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 101000
#define ll long long
ll tree1[maxn<<2];
ll tree2[maxn<<2];
ll num1[maxn];
ll num2[maxn];
int n,m;
void update1(int now){
	tree1[now]=tree1[now<<1]+tree1[now<<1|1];
}
void update2(int now){
	tree2[now]=tree2[now<<1]+tree2[now<<1|1];
}
void build1(int l, int r, int now){
	if(l==r){
		tree1[now]=num1[l];
		return ;
	}
	int mid=(l+r)/2;
	build1(l, mid, now<<1);
	build1(mid+1, r, now<<1|1);
	update1(now);
}
void build2(int l, int r, int now){
	if(l==r){
		tree2[now]=num2[l];
		return ;
	}
	int mid=(l+r)/2;
	build2(l, mid, now<<1);
	build2(mid+1, r, now<<1|1);
	update2(now);
}
void change1(int l, int r, int now, int x, ll c){
	if(l==r){
		tree1[now]=c;
		return;
	}
	int mid=(l+r)/2;
	if(x<=mid) change1(l, mid, now<<1, x, c);
	else change1(mid+1, r, now<<1|1, x, c);
	update1(now);
}
void change2(int l, int r, int now, int x, ll c){
	if(l==r){
		tree2[now]=c;
		return;
	}
	int mid=(l+r)/2;
	if(x<=mid) change2(l, mid, now<<1, x, c);
	else change2(mid+1, r, now<<1|1, x, c);
	update2(now);
}
ll seartch1(int l, int r, int now, int i, int j){
	if(i<=l&&r<=j) return tree1[now];
	ll ans=0;
	int mid=(l+r)/2;
	if(i<=mid) ans+=seartch1(l, mid, now<<1, i, j);
	if(j>mid) ans+=seartch1(mid+1, r, now<<1|1, i, j);
	return ans;
}
ll seartch2(int l, int r, int now, int i, int j){
	if(i<=l&&r<=j) return tree2[now];
	ll ans=0;
	int mid=(l+r)/2;
	if(i<=mid) ans+=seartch2(l, mid, now<<1, i, j);
	if(j>mid) ans+=seartch2(mid+1, r, now<<1|1, i, j);
	return ans;
}
int main(){
		scanf("%d %d",  &n, &m);
		for(int i=1;i<=n;i++){
			scanf("%lld",  &num1[i]);
			num2[i]=num1[i]*(ll)(n-i+1);
		}
		build1(1, n, 1);
		build2(1, n, 1);
		long long a, b, c;
		while(m--){
			cin>>c>>a>>b;
			if(c==1){
				cout<<seartch2(1, n, 1, (int)a, (int)b)-(ll)(n-b)*seartch1(1, n, 1, (int)a, (int)b)<<endl;
			}else{
				change1(1, n, 1, (int)a, b);
				change2(1, n, 1, (int)a, b*(ll)(n-a+1));
			}
		}
	return 0;
}
发布了70 篇原创文章 · 获赞 22 · 访问量 6506

猜你喜欢

转载自blog.csdn.net/weixin_44410512/article/details/100151556