线段树50pts求调已经检查好多次了,并且这道题鸽了将近四个月()
查看原帖
线段树50pts求调已经检查好多次了,并且这道题鸽了将近四个月()
526895
WYZ20030051楼主2023/7/6 19:06

直接放代码吧,我实在找不着错了(太蒻)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<map>
using namespace std;
#define MAXN 100010 
#define ll long long
#define L(x) x<<1
#define R(x) x<<1|1
int n,m;
ll data[MAXN];
ll tresum[MAXN*4];
ll tremax[MAXN*4];
//由于一个数开根号后很快会变为1,所以可以判断开根号的值是否为1来减少开根号的次数(开到0会需要很多次)
//所以用一个新的数组来记录开根号后的值 
int read()
{
	char ch;
	while((ch=getchar())>'9' || (ch<'0'));
		int rs=ch-'0';
	while((ch=getchar())<='9' && (ch>='0'))
		rs=rs*10+ch-'0';
	return rs;
}
void pushup(int x)
{
	tresum[x]=tresum[L(x)]+tresum[R(x)];
	tremax[x]=max(tremax[L(x)],tremax[R(x)]);
}
void build(int k,int l,int r)
{
	if(l==r)
	{
		tresum[k]=tremax[k]=data[l];
		return;
	}
	int mid=(l+r)/2;
	build(L(k),l,mid);
	build(R(k),mid+1,r);
	pushup(k);
}
void change(int k,int l,int r,int x,ll v)
{
	if(l==r)
	{
		tresum[k]=(long long)sqrt(tresum[k]);
		tremax[k]=(long long)sqrt(tremax[k]);
		return ;
	}
	if(tremax[k]<=1)
		return ;
	int mid=(l+r)/2;
	if(mid>=x)
		change(L(k),l,mid,x,v);
	if(mid<v)
		change(R(k),mid+1,r,x,v);
	pushup(k);
}
ll query(int k,int l,int r,int x,int y)
{
	if(y<l || x>r)   //区间[x,y]与区间[l,r]无交集,则return 
		return 0;
	if(x<=l && r<=y)  //区间[l,r]完全在区间[x,y]内 
		return tresum[k]; //返回已经维护的值
	int mid=(l+r)/2;
	ll res=0;
	if(mid>=x)
		res=query(L(k),l,mid,x,y);
	if(mid<y)
		res+=query(R(k),mid+1,r,x,y);
	return res;
}
int main()
{
	memset(tresum,0,sizeof(tresum));
	memset(tremax,0,sizeof(tremax));
	n=read();
	for(int i=1;i<=n;i++)
		data[i]=read();
	m=read();
	build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		int x,l,r;
		x=read();
		l=read();
		r=read();
		if(l>r)
			swap(l,r);
		if(x==0)
			change(1,1,n,l,r);
		if(x==1)
			printf("%lld\n",query(1,1,n,l,r));
	}
	return 0;
}
2023/7/6 19:06
加载中...