HDU 4027

这道题最初思路是线段树维护每段区间被开平方的次数,然后最终query的时候取个循环,但是这样时间复杂度还是受不住

这道题的非线性导致了不小的麻烦,死板的想要依然遵循线段树延迟修改最后无路可走,所以,这道题的线段树很特殊,每次更新,都更新到最终的叶子节点为止(这也是看题解才收获的,还是需要训练量培养思路生成)

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
using namespace std;

const int maxn= 1e5+5;
typedef unsigned long long LL;

struct Seg
{
	int l, r;
	LL sum;
}segTree[maxn<<2];
int n, m, op, x, y;

void Build(int x, int l, int r)
{
	segTree[x].l= l;
	segTree[x].r= r;
	if (l== r){
		scanf("%llu", &segTree[x].sum);
		return;
	}
	int mid= (l+r)>>1;
	Build(x<<1, l, mid);
	Build(x<<1|1, mid+1, r);
	segTree[x].sum= segTree[x<<1].sum+segTree[x<<1|1].sum;
}
void Update(int x, int l, int r)
{
	if (l> r){
		return;
	}
	if (segTree[x].sum== (LL)(segTree[x].r-segTree[x].l+1)){
		return;
	}
	if (segTree[x].l== segTree[x].r){
		segTree[x].sum= sqrt(1.0*segTree[x].sum);
		return;
	}
	int mid= (segTree[x].l+segTree[x].r)>>1;
	if (mid>= r){
		Update(x<<1, l, r);
	}
	else if (mid< l){
		Update(x<<1|1, l, r);
	}
	else{
		Update(x<<1, l, mid);
		Update(x<<1|1, mid+1, r);
	}
	segTree[x].sum= segTree[x<<1].sum+segTree[x<<1|1].sum;
}
LL Query(int x, int l, int r)
{
	if (l> r){
		return 0;
	}
	if (l== segTree[x].l && r== segTree[x].r){
		return segTree[x].sum;
	}
	int mid= (segTree[x].l+segTree[x].r)>>1;
	if (mid>= r){
		return Query(x<<1, l, r);
	}
	else if (mid< l){
		return Query(x<<1|1, l, r);
	}
	else{
		return Query(x<<1, l, mid)+Query(x<<1|1, mid+1, r);
	}
}
int main()
{
	int kase= 0;
	while (~scanf("%d", &n)){
		Build(1, 1, n);
		scanf("%d", &m);
		printf("Case #%d:\n", ++kase);
		while (m--){
			scanf("%d %d %d", &op, &x, &y);
			if (x> y){
				swap(x, y);
			}
			if (op){
				printf("%llu\n", Query(1, x, y));
			}
			else{
				Update(1, x, y);
			}
		}
		putchar('\n');
	}
}
posted @ 2021-05-20 21:15  IdiotNe  阅读(49)  评论(0编辑  收藏  举报