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
Sample Output
101
11
11
HINT
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9
题意:两种操作 1 查询 l—r的区间和
2 区间l—r的数字都要开根号
思路:势能线段树,因为n<=1e5 所以最多开方5次即可结束变为1(可以不使用lazy延迟标记),暴力更新即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN=1e5+5;
typedef long long ll;
struct node
{
ll sum;
int flag;
}tree[MAXN<<2];
int a[MAXN];
void pushup(int rt)
{
tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
tree[rt].flag=tree[rt<<1].flag&tree[rt<<1|1].flag;
}
void build(int l,int r,int rt)
{
if(l==r)
{
tree[rt].sum=a[l]; //赋值
if(tree[rt].sum==0||tree[rt].sum==1)
tree[rt].flag=1;
else
tree[rt].flag=0;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if(tree[rt].flag) return;
if(L<=l&&r<=R) //完全覆盖 L R 为输入的
{
if(l==r){
tree[rt].sum=sqrt(tree[rt].sum);
if(tree[rt].sum==1||tree[rt].sum==0)
tree[rt].flag=1;
return ;
}
}
int m=(l+r)>>1;
if(L<=m) update(L,R,lson);
if(m<R) update(L,R,rson);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return tree[rt].sum;
}
int m=(l+r)>>1;
ll ret=0;
if(L<=m) ret+=query(L,R,lson);
if(m<R) ret+=query(L,R,rson);
return ret;
}
int main()
{
int m,n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
scanf("%d",&m);
while(m--){
int k,x,y;
scanf("%d%d%d",&k,&x,&y);
if(x>y) swap(x,y);
if(k==1)
printf("%lld\n",query(x,y,1,n,1));
if(k==2)
update(x,y,1,n,1);
}
return 0;
}