Codeforces Beza‘s Hangover(线段树)

Codeforces Beza‘s Hangover(线段树)_第1张图片

题意

  给出三个数n,m,q,分别代表初始n个小时里每个小时喝的什么酒,m代表有m种酒(注意:m中可能出现n中没有出现过的酒),记录这些酒的容量,q次询问。
  询问的时候有两种情况,
· 1 X Y 代表把第X小时喝的酒换成名字为Y的酒
· 2 L R 表示判断第L小时到第R小时这R-L+1个小时里喝的酒能否让Beza宿醉,如果喝的毫升数小于等于喝酒时间(单位:分钟)的一半不醉,否则醉

思路

线段树模板题,单点修改,区间求和,判断区间和是否小于等于区间时间的一半就ok。
cin卡TLE 77了,scanf又AC了。。。。不同的OJ性能不一样,如果还是卡TLE,建议用快读。

AC代码:

#include
using namespace std;
const int maxn=2e5+10;
char d[maxn][25],s[25],y[25];
int v,n,m,q,a[maxn],cic,x,l,r,tree[maxn*4];
map<string,int> mp;
void build(int l,int r,int node){
	if(l == r){
		tree[node]=a[l];
		return ;
	}
	int mid = (l+r)/2;
	build(l,mid,node*2);
	build(mid+1,r,node*2+1);
	tree[node] = tree[node*2]+tree[node*2+1];
}

void update(int node,int l,int r,int x,int y){
	if(l==r){
		tree[node]=y;
		return ;
	}
	int mid = (l+r)/2;
	if(x<=mid) update(node*2,l,mid,x,y);
	else update(node*2+1,mid+1,r,x,y);
	tree[node] = tree[node*2]+tree[node*2+1]; 
}

int query(int node,int l,int r,int x,int y){// (l,r)是目前区间 (x,y)是要查询的区间 
	if(x<=l && r<=y) return tree[node];
	int mid = (l+r)/2;
	int res = 0;
	if(x <= mid) res += query(node*2,l,mid,x,y);
	if(y > mid) res += query(node*2+1,mid+1,r,x,y);
	return res; 
}

int main() {
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1; i<=n; i++) cin>>d[i];
	while(m--) scanf("%s%d",s,&v),mp[s]=v;
	for(int i=1; i<=n; i++) a[i] = mp[d[i]];
	build(1,n,1);
	while(q--) {
		scanf("%d",&cic);
		if(cic==1) {
			scanf("%d%s",&x,y);
			update(1,1,n,x,mp[y]); //修改第x小时的drink为y
		} else {
			scanf("%d%d",&l,&r);
			int ans = query(1,1,n,l,r);
			if(ans > (r-l+1)*30) printf("YES\n");
			else printf("NO\n");
		}
	}
}

附上一篇关于线段树讲解的文章
什么是“线段树”?

你可能感兴趣的:(数据结构,算法)