把一段区间里的每个数都开方 求区间和
可以发现最多开方开6次就能都变为1 所以可以hei暴力地一个点一个点地改 具体操作我用的和buildtree差不多
还要注意 是当前区间的最大值<=1时才不处理 我写的==1QAQ 导致BZOJ上有一个点超时
#include#include #include #include #include #include #include using namespace std;#define ll long long#define rg register#define lson o<<1#define rson o<<1|1const int N=100000+5,M=200000+5,inf=0x3f3f3f3f,P=19650827;int n,m;ll a[N],sum[N<<2],mx[N<<2];template void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x;} void pushup(int o){ sum[o]=sum[lson]+sum[rson]; mx[o]=max(mx[lson],mx[rson]);} void update(int o,int l,int r,int x,int y){ if(r >1; update(lson,l,mid,x,y),update(rson,mid+1,r,x,y); pushup(o);} void buildtree(int o,int l,int r){ if(l==r) {sum[o]=mx[o]=a[l];return;} int mid=(l+r)>>1; buildtree(lson,l,mid); buildtree(rson,mid+1,r); pushup(o);} ll query(int o,int l,int r,int x,int y){ ll ans=0; if(r >1; ans+=query(lson,l,mid,x,y); ans+=query(rson,mid+1,r,x,y); return ans;} int main(){ rd(n); for(int i=1;i<=n;++i) rd(a[i]); buildtree(1,1,n); rd(m); while(m--){ int k,l,r; rd(k),rd(l),rd(r); if(l>r) swap(l,r); if(k==2) update(1,1,n,l,r); else printf("%lld\n",query(1,1,n,l,r)); } return 0;}