省选专练之数据结构HDU5828

Rikka with Sequence

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)


Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has an array A with n numbers. Then he makes m operations on it. 

There are three type of operations:

1 l r x : For each i in [l,r], change A[i] to A[i]+x
2 l r : For each i in [l,r], change A[i] to ⌊A√[i]⌋
3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]

It is too difficult for Rikka. Can you help her?
 
Input
The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.

For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.

It is guaranteed that 1<=A[i],x<=100000.
 
Output
For each operation of type 3, print a lines contains one number -- the answer of the query.
 
Sample Input
1
5 5
1 2 3 4 5
1 3 5 2
2 1 4
3 2 4
2 3 5
3 1 5
 
Sample Output
5
6

线段树好题

这个本来按照区间开根的思想考虑了维护一段权重相同的值。

但最后这个被卡了

232323 +6 sqrt
然后:

维护区间Max-Min<=1的序列,这个序列讨论复杂度要低一些。

存在区间Set

所以注意先做set的lazy

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc (p<<1)
#define rc (p<<1|1)
const int N=2e5+1000;
typedef int INT;
#define int long long
inline void read(int &x){
	x=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int n,m;
int val[N]={};
struct Segment_Tree{
	struct Node{
		int sum,lson,rson,Mn,Mx,addlazy,setlazy;
	}T[N<<2];
	inline void PushUp(int p){
		T[p].sum=T[lc].sum+T[rc].sum;
		T[p].Mn=min(T[lc].Mn,T[rc].Mn);
		T[p].Mx=max(T[lc].Mx,T[rc].Mx);
	}
	inline void PushNow(int p,int flag,int val){
		if(flag==1){
			T[p].sum+=(T[p].rson-T[p].lson+1)*val;
			T[p].addlazy+=val;
			T[p].Mx+=val;
			T[p].Mn+=val;
		}
		else{
			T[p].addlazy=0;
			T[p].sum=(T[p].rson-T[p].lson+1)*val;
			T[p].setlazy=val;
			T[p].Mx=T[p].Mn=val;
		}
	}
	inline void PushDown(int p){
		if(T[p].setlazy!=-1){
			PushNow(lc,0,T[p].setlazy);
			PushNow(rc,0,T[p].setlazy);
			T[p].setlazy=-1;
		}
		if(T[p].addlazy){
			PushNow(lc,1,T[p].addlazy);
			PushNow(rc,1,T[p].addlazy);
			T[p].addlazy=0;
		}
	}
	inline void Build(int p,int l,int r){
		T[p].lson=l;
		T[p].rson=r;
		T[p].setlazy=-1;
		T[p].addlazy=0;		
		if(l==r){
			T[p].sum=T[p].Mn=T[p].Mx=val[l];
			return;
		}
		int mid=(l+r)/2;
		Build(lc,l,mid);
		Build(rc,mid+1,r);
		PushUp(p);
	}
	inline void update(int p,int l,int r,int val){
		if(l<=T[p].lson&&T[p].rson<=r){ 
			PushNow(p,1,val);
			return;
		}
		PushDown(p);
		int mid=(T[p].lson+T[p].rson)/2;
		if(l<=mid)
		update(lc,l,r,val);
		if(mid< r)
		update(rc,l,r,val);
		PushUp(p);
	}
	inline void Sqr(int p,int l,int r){
		if(l<=T[p].lson&&T[p].rson<=r&&T[p].Mx-T[p].Mn<=1){
			int SqrMx=sqrt(T[p].Mx);
			int SqrMn=sqrt(T[p].Mn);
			if(SqrMx==SqrMn){
				PushNow(p,0,SqrMx);
			}
			else{
				PushNow(p,1,SqrMx-T[p].Mx);
			}
		}
		else{
			PushDown(p);
			int mid=(T[p].lson+T[p].rson)/2;
			if(l<=mid)
			Sqr(lc,l,r);
			if(mid<r )
			Sqr(rc,l,r);
			PushUp(p);	
		}
	}
	inline int Query(int p,int l,int r){
		if(l<=T[p].lson&&T[p].rson<=r){
			return T[p].sum;
		}
		PushDown(p);
		int ret=0;
		int mid=(T[p].lson+T[p].rson)/2;
		if(l<=mid)ret+=Query(lc,l,r);
		if(mid <r)ret+=Query(rc,l,r);
		return ret;
	}
}T;
INT main(){
//	freopen("HDU5828.in","r",stdin);
	int Case;
	read(Case);
	while(Case--){
		read(n);
		read(m);
		for(int i=1;i<=n;i++){
			read(val[i]);
		}
		T.Build(1,1,n);
//		cout<<"here"<<'\n';
		while(m--){
//			cout<<m<<'\n';
			int opt;
			read(opt);
			if(opt==1){
				int l,r,val;
				read(l);
				read(r);
				read(val);
				T.update(1,l,r,val);
			}
			if(opt==2){
				int l,r;
				read(l);
				read(r);
				T.Sqr(1,l,r);
			}
			if(opt==3){
				int l,r;
				read(l);
				read(r);
				cout<<T.Query(1,l,r)<<'\n';
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/fcb_x/article/details/81171711