bzoj3211 花神游历各国
线段树区间开方。。。直接暴力改到叶子。。
一开始数组开小RE。。。
#include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cstdlib> #include<iostream> #include<algorithm> #define l(a) (((a)<<1)) #define r(a) (((a)<<1)+1) #define clr(a,x) memset(a,x,sizeof(a)) #define rep(i,l,r) for(int i=l;i<r;i++) typedef long long ll; using namespace std; int read() { char c=getchar(); int ans=0,f=1; while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ ans=ans*10+c-'0'; c=getchar(); } return ans*f; } const int maxn=500010; struct node{ int l,r,mx; ll sum; }; node x[maxn]; void maintain(int a) { x[a].mx=max(x[l(a)].mx,x[r(a)].mx); x[a].sum=x[l(a)].sum+x[r(a)].sum; } void build(int a,int l,int r) { x[a].l=l,x[a].r=r; if(l==r){ x[a].mx=x[a].sum=read(); return; } int mid=(l+r)>>1; build(l(a),l,mid); build(r(a),mid+1,r); maintain(a); } ll find(int a,int l,int r) { if(l==x[a].l&&r==x[a].r){ return x[a].sum; } int mid=(x[a].l+x[a].r)>>1; if(r<=mid) return find(l(a),l,r); if(l>mid) return find(r(a),l,r); return find(l(a),l,mid)+find(r(a),mid+1,r); } void modify(int a,int l,int r) { if(x[a].mx<=1) return; if(x[a].l==x[a].r){ x[a].sum=floor(sqrt(x[a].sum)); x[a].mx=floor(sqrt(x[a].mx)); return; } int mid=(x[a].l+x[a].r)>>1; if(r<=mid) modify(l(a),l,r); else if(l>mid) modify(r(a),l,r); else{ modify(l(a),l,mid); modify(r(a),mid+1,r); } maintain(a); } int main() { clr(x,0); int n=read(); build(1,1,n); int m=read(); while(m--){ int opt=read(),L=read(),R=read(); if(opt==1){ printf("%lld\n",find(1,L,R)); }else{ modify(1,L,R); } } return 0; }
3211: 花神游历各国
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1420 Solved: 548
[Submit][Status][Discuss]
Description
Input
Output
每次x=1时,每行一个整数,表示这次旅行的开心度
Sample Input
4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
Sample Output
101
11
11
11
11
HINT
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9