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
他明明是个链我还打了个树链剖分感觉我就是个傻逼
线段树裸题,开方的话没法直接开,那么我有一个大(sang)胆(bing)的想法——暴力
的确慢了点但还是过了,记得要开long long
代码如下:
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; typedef long long ll; struct trnode{ int l,r,lc,rc; ll c,s; }tr[2100000];int trlen; ll a[110000]; void bt(int l,int r) { int now=++trlen; tr[now].l=l;tr[now].r=r;tr[now].c=tr[now].s=a[l]; tr[now].lc=tr[now].rc=-1; if(l<r) { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c; tr[now].s=max(tr[tr[now].lc].s,tr[tr[now].rc].s); } } void change(int now,int l,int r) { if(tr[now].s<=1)return ; if(tr[now].l==tr[now].r){tr[now].c=ll(sqrt(tr[now].c));tr[now].s=tr[now].c;return ;} int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; if(r<=mid)change(lc,l,r); else if(mid+1<=l)change(rc,l,r); else { change(lc,l,mid); change(rc,mid+1,r); } tr[now].c=tr[lc].c+tr[rc].c; tr[now].s=max(tr[lc].s,tr[rc].s); } ll findsum(int now,int l,int r) { if(tr[now].l==l&&r==tr[now].r)return tr[now].c; int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; if(r<=mid)return findsum(lc,l,r); else if(mid+1<=l)return findsum(rc,l,r); else return findsum(lc,l,mid)+findsum(rc,mid+1,r); } int n; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); trlen=0;bt(1,n); int m; scanf("%d",&m); while(m--) { int l,r,k; scanf("%d%d%d",&k,&l,&r); if(k==2)change(1,l,r); else printf("%lld\n",findsum(1,l,r)); } return 0; }
by_lmy