1. 程式人生 > >題解 luogu P2068 【統計和】

題解 luogu P2068 【統計和】

小水題

話說rayment大佬噓寒問暖兩天,差點教會我怎麼用splay求區間和。這題我差點就下狠手使用splay了。

線段樹1的退化版,change區間變成了change一個數,延遲標記?不存在!

所以我們只需要簡單建一棵線段樹,然後輕鬆模擬就好了。建樹其實只需要將樹的區間搞出來,區間和由於初始值為0,所以根本不需要求。

#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
struct segment_tree{
	int l,r;
	int v;
}t[4*maxn];
void build(int x,int l,int r){
	t[x].l=l;t[x].r=r;
	t[x].v=0;//因為初始值是0,所以建樹不需要那麼麻煩
	int mid=(l+r)/2;
	if (l==r)return ;
	build(x*2,l,mid);
	build(x*2+1,mid+1,r);//建樹
}
int y,z;
void change(int x,int l,int r){
	int mid=(l+r)/2;
	t[x].v+=z;//只改變一個值,所以每個包含只需要加一遍
	if (l==r)return ;
	if (mid>=y)change(x*2,l,mid);
	else change(x*2+1,mid+1,r);
}
int ask(int x,int l,int r){
	if (l<=t[x].l&&r>=t[x].r)return t[x].v;//如果完全包含,則直接返回
	int mid=(t[x].l+t[x].r)/2;
	int  v=0;
	if (l<=mid) v+=ask(x*2,l,r);
	if (r>mid) v+=ask(x*2+1,l,r);//遞迴
	return v;//詢問區間和
}
int main(){
	int i,j,n,m;
	cin>>n;
	build(1,1,n);
	cin>>m;
	for (i=1;i<=m;i++){
		char x;
		cin>>x>>y>>z;
		if (x=='x')change(1,1,n);
		else cout<<ask(1,y,z)<<endl;
	}
	return 0;
}//主函式部分,沒什麼意義

線段樹板子題,剛學線段樹的oier也可以直接切了,加點經驗。