【bzoj3038】上帝造题的七分钟2 线段树

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3038

线段树是我最不熟悉的东西之一,于是找几道题搞搞

这题就很简单了

有一个神奇的优化:

如果一个结点值为0或者1就不再更新;

如果一棵树左右儿子都不再更新,它也不再更新

#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define MAXN 100010
#define FILE "read"
#define up(i,j,n) for(ll i=j;i<=n;i++)
#define dn(i,j,n) for(ll i=j;i>=n;i--)
namespace INIT{
	char buf[1<<15],*fs,*ft;
	inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline ll read(){
		ll x=0,f=1;  char ch=getc();
		while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
		while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
		return x*f;
	}
}using namespace INIT;
ll n,m,a[MAXN],tr[MAXN<<2],vis[MAXN<<2];
void build(ll l,ll r,ll p){
	if(l>r)  return;
	if(l==r)  {tr[p]=a[l]; if(a[l]==0||a[l]==1) vis[p]=1; return;}
	ll mid=(l+r)>>1;
	build(l,mid,p<<1);  build(mid+1,r,p<<1|1);
	tr[p]=tr[p<<1]+tr[p<<1|1];
	vis[p]=vis[p<<1]&vis[p<<1|1];
}
void change(ll l,ll r,ll p,ll x,ll y){
	if(l>r)  return;
	if(vis[p])  return;
	if(l==r) {tr[p]=(ll)sqrt(tr[p]*1.0); if(tr[p]==0||tr[p]==1) vis[p]=1; return;}
	ll mid=(l+r)>>1;
	if(mid>=y)  change(l,mid,p<<1,x,y);
	else if(midr||y=r)  return tr[p];
	ll mid=(l+r)>>1;
	return ask(l,mid,p<<1,x,y)+ask(mid+1,r,p<<1|1,x,y);
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read();
	up(i,1,n)  a[i]=read();
	build(1,n,1);
	m=read();
	up(i,1,m){
		ll flag=read(),x=read(),y=read();
		if(x>y)  swap(x,y);
		if(flag==0) change(1,n,1,x,y);
		else printf("%lld\n",ask(1,n,1,x,y));
	}
	return 0;
}



你可能感兴趣的:(线段树)