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

来源:互联网 发布:淘宝网页卖家中心在哪 编辑:程序博客网 时间:2024/03/29 22:48

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

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

这题就很简单了

有一个神奇的优化:

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

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

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>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(mid<x)  change(mid+1,r,p<<1|1,x,y);else{change(l,mid,p<<1,x,mid);change(mid+1,r,p<<1|1,mid+1,y);}tr[p]=tr[p<<1]+tr[p<<1|1];vis[p]=vis[p<<1]&vis[p<<1|1];}ll ask(ll l,ll r,ll p,ll x,ll y){if(x>r||y<l)  return 0;if(x<=l&&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;}



1 0
原创粉丝点击