Poj 3468 A Simple Problem with Integers

需要lazy思想的線段樹

原本都關機睡覺了,來了靈感,雙重維護

聽說過lazy的想法,實現方式是自己想到的,增量+子區間總和

5Y

3*TLE

1*WA

這個可以當做自己的模板了吧~~

TLE的關鍵點在於

insert和sum的結束條件都不能是T[w].l==T[w].r這樣比O(n)的樸素算法還慢..貌似

想要加快sum,需要維護下段總和

想要加快insert,需要維護區間上統一增量

二者缺一不可

在多次實現中和刷牙+思考終於想出...

滿足感滿滿

#include<stdio.h>
#define LL long long
struct line{
	int l,r;
	LL x,s;
	}T[1<<18];
void build(int s,int t,int w){
	T[w].l=s;T[w].r=t;
	T[w].x=0;T[w].s=0;
	if(s==t)return;
	int mid=(s+t)/2;
	build(s,mid,w*2);
	build(mid+1,t,w*2+1);
	}
void insert(int s,int t,int w,LL val){
	if(T[w].l==s&&T[w].r==t){T[w].x+=val;return;}
	T[w].s+=(t+1-s)*val;
	int mid=(T[w].l+T[w].r)/2;
	if(s>mid)insert(s,t,w*2+1,val);
	else if(t<=mid)insert(s,t,w*2,val);
	else {
		insert(s,mid,w*2,val);
		insert(mid+1,t,w*2+1,val);
		}
	}
LL sum(int s,int t,int w){
	LL tp=(t+1-s)*T[w].x; 
	if(T[w].l==s&&T[w].r==t)return tp+T[w].s;
	int mid=(T[w].l+T[w].r)/2;
	if(s>mid)return tp+sum(s,t,w*2+1);
	else if(t<=mid)return tp+sum(s,t,w*2);
	else {
		return tp+sum(s,mid,w*2)+sum(mid+1,t,w*2+1);
		}	
	}
int main(){
	int N,Q;
	while(scanf("%d%d",&N,&Q)!=EOF){
		build(1,N,1);
		int i,j,s,t;
		LL x;
		char c;
		for(i=1;i<=N;i++){
			scanf("%lld%*c",&x);
			insert(i,i,1,x);
			}
		for(i=1;i<=Q;i++){
			scanf("%c",&c);
			if(c=='Q'){
				scanf("%d %d%*c",&s,&t);
				printf("%lld\n",sum(s,t,1)); 
				continue;
				}
			scanf("%d %d %lld%*c",&s,&t,&x);
			insert(s,t,1,x);
			}
		} 
	return 0;
	}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章