HDU4027 Can you answer these queries 线段树区间求和+剪枝

给了你n,然后n个数字在一个数组中,接下来m个询问,每个询问三个数字 t,x,y,若t==0,那么修改区间[x,y]的每一个值,变为原来每个位置上的数 开根号取整,若t==1,那么对区间[x,y]求和

由于n,m,很大,所以树状数组铁定超时,若直接用线段树来做区间修改,那么也是超时,这类题目没别的方法了,静心剪枝,发现题目给的数据范围为2^63,有没有发现,2^63开根号 绝对不需要开10次,就能到1,到1以后就不需要再开了,意思就是若有某个区间[x,y]每一个点的值都为1时,这一段区间事实上是不需要处理的,怎么判断呢,简单,这个区间的和 等于 区间大小就是了,

都改好了 也不TLE了,也不WA了,但是一直RE,搞不懂,直到最后也没搞懂,最后有队友说题目给的区间 [x,y], x的值不一定比y小,所以需要判别一下,题目在交代x,y的取值范围时,确实没有说x<y,所以算是自己粗心吧,长记性了

#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype>

#define ll long long

#define LL __int64

#define eps 1e-8

#define inf 0xfffffff

//const ll INF = 1ll<<61;

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int > P;
//vector<pair<int,int> > ::iterator iter;
//
//map<ll,int >mp;
//map<ll,int >::iterator p;

const int N = 100000 + 5;

typedef struct Node {
	int l,r;
	LL sum;
};

Node tree[N * 4];

LL a[N];

int n;

void build_tree(int left,int right,int id) {
	tree[id].l = left;
	tree[id].r = right;
	tree[id].sum = 0;
	if(left == right) {
		tree[id].sum = a[left];
		return;
	}
	int mid = (left + right)>>1;
	build_tree(left,mid,id * 2);
	build_tree(mid+1,right,id * 2 + 1);
	tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

void update(int left,int right,int id) {
	if(tree[id].l == left && tree[id].r == right) {
		if(tree[id].sum ==right - left + 1) return;//区间和等于区间长度没必要更新处理
		else if(left == right) {
			tree[id].sum = sqrt(tree[id].sum * 1.0);
			return ;
		}
	}
	LL mid = (tree[id].l + tree[id].r)>>1;
	if(right <= mid)
		update(left,right,id * 2);
	else  if(left > mid)
		update(left,right,id * 2 + 1);
	else {
		update(left,mid,id * 2);
		update(mid + 1,right,id * 2 + 1);
	}
	tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

LL query(int left,int right,int id) {
	if(tree[id].l == left && tree[id].r == right) return tree[id].sum;
	int mid = (tree[id].l + tree[id].r)>>1;
	if(right <= mid)
		return query(left,right,id * 2);
	else if(left > mid)
		return query(left,right,id * 2 + 1);
	else
		return query(left,mid,id * 2) + query(mid + 1,right,id * 2 + 1);
}

int main() {
	int	Case = 0;
	while(scanf("%d",&n) == 1) {
		for(int i=1;i<=n;i++)
			scanf("%I64d",&a[i]);
		build_tree(1,n,1);
		int m;
		scanf("%d",&m);
		int t,x,y;
		printf("Case #%d:\n",++Case);
		while(m--) {
			scanf("%d %d %d",&t,&x,&y);
			if(x > y)
				swap(x,y);
			if(t == 0) {
				update(x,y,1);
			}
			else {
				printf("%I64d\n",query(x,y,1));
			}
		}
		puts("");
	}
	return 0;
}

HDU4027 Can you answer these queries 线段树区间求和+剪枝,布布扣,bubuko.com

时间: 2024-10-12 09:18:55

HDU4027 Can you answer these queries 线段树区间求和+剪枝的相关文章

HDU 4027 Can you answer these queries? (线段树+区间点修改)

题意:给你 n 个数,m个询问(c,x,y) c==0 把x,y区间的值变为原来的平方根(向下取整) c==1 计算x,y区间的和. 利用1的开方永远为1剪枝.. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> //#include<map> #include<cmath> #include<iostream> #include

hdu 4027 Can you answer these queries? 线段树区间开根号,区间求和

Can you answer these queries? Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5195 Description A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our secret weapo

HDU-Can you answer these queries? (线段树+区间修改)

Problem Description A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our secret weapon to eliminate the battleships. Each of the battleships can be marked a value of endurance. For every attack of ou

HDU4027Can you answer these queries?(线段树区间和,坑)

Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 8674 Accepted Submission(s): 1971 Problem Description A lot of battleships of evil are arranged in a line before the b

HDU 4027 Can you answer these queries?(线段树 区间不等更新)

题意  输入n个数  然后有两种操作   输入0时将给定区间所有数都变为自己的开方   输入1输出给定区间所有数的和 虽然是区间更新  但每个点更新的不一样  因此只能对单点进行更新  其实一个点最多被更新7次  2^64开平方7次后就变为1了  如果某个区间的数都变为了1  那么对这个区间的开方就不用考虑了   另外要注意给你的区间可能是反的 #include <bits/stdc++.h> #define lc p<<1,s,mid #define rc p<<1|

HDU - 4027 Can you answer these queries? (线段树区间更新+思维)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027 题意:给定两种操作,查询(求出区间内的和),更新(区间内每个值都开根号,取整数) 题目给出所有数字之和小于263,所以最大的数最多7次也就变成1.所以在更新的时候加个判断条件,提前结束. 然后这道题目还有个坑,L有可能比R大,需要交换一下,(╬▔皿▔) . 1 #include <cstdio> 2 #include <algorithm> 3 #include <cmat

HDU 4027 Can you answer these queries?(线段树,区间更新,区间查询)

题目 线段树 简单题意: 区间(单点?)更新,区间求和 更新是区间内的数开根号并向下取整 这道题不用延迟操作 //注意: //1:查询时的区间端点可能前面的比后面的大: //2:优化:因为每次更新都是开平方,同一个数更新有限次数就一直是1了,所以可以这样优化 #include <stdio.h> #include<math.h> #define N 100010 #define LL __int64 #define lson l,m,rt<<1 #define rson

HDU 4027 Can you answer these queries? (线段树区间求和)

Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submission(s): 12290    Accepted Submission(s): 2912 Problem Description A lot of battleships of evil are arranged in a line before

HDU 4027 Can you answer these queries? 线段树裸题

题意: 给定2个操作 0.把区间的每个数sqrt 2.求和 因为每个数的sqrt次数很少,所以直接更新到底,用个标记表示是否更新完全(即区间内的数字只有0,1就不用再更新了) #include<stdio.h> #include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<queue> #include<set> #incl