您的位置:首页 > 产品设计 > UI/UE

hdu 4027 Can you answer these queries? (线段树)

2017-05-13 20:31 363 查看
上题: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 oursecret weapon, it could decrease the endurance of a consecutive part of battleships by make their endurance to the square root of it original value of endurance. During the series of attack of our secret weapon, the commander wants to evaluate the effect ofthe weapon, so he asks you for help. You are asked to answer the queries that the sum of the endurance of a consecutive part of the battleship line. Notice that the square root operation should be rounded down to integer.InputThe input contains several test cases, terminated by EOF.   For each test case, the first line contains a single integer N, denoting there are N battleships of evil in a line. (1 <= N <= 100000)   The second line contains N integers Ei, indicating the endurance value of each battleship from the beginning of the line to the end. You can assume that the sum of all endurance value is less than 2 63.   The next line contains an integer M, denoting the number of actions and queries. (1 <= M <= 100000)   For the following M lines, each line contains three integers T, X and Y. The T=0 denoting the action of the secret weapon, which will decrease the endurance value of the battleships between the X-th and Y-th battleship, inclusive. The T=1 denoting the queryof the commander which ask for the sum of the endurance value of the battleship between X-th and Y-th, inclusive. OutputFor each test case, print the case number at the first line. Then print one line for each query. And remember follow a blank line after each test case.Sample Input
10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8
Sample Output
Case #1:
19
7
6
题意:
题意就是有一个序列,和m组数(a,b,c),其中a等于1的时候表示的是查询从b~c的和,而a=0表示的是将b~c之间的数全部开平方。真是渣渣 ,看到一道题就觉得是好题。。。
做法:起初看着道题的时候 认为这不就是很裸的 字段区间更新吗,但是敲到一半,发现根本不对好吗,他现在要做的对于每个开平方的数求值,而不是同加或者同减一个数,所以我们是没有办法更新一个区段和的,因为很明显,sqrt(1+2)!=sqrt(1)+sqrt(2)的,况且我们不能把当前的状态,传到下面。之后,我们可以看到他每次更新的值的方法是开平方,最大值为2的63次方,那么也就是他最多开7次之后这个数值必为1,那么这之后我们就不必在更新了,这样他的复杂度最多为o(7n)所以这道题的正确做法就是,单点更新,之后求和。对了,这道题有个坑点,就是 x和y之间,那么也就是说他们没有确定x和y的大小关系
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=100002;
long long sum[maxn<<2],mark[maxn<<2];
void pushup(int rt)
{
sum[rt]=sum[rt<
4000
<1]+sum[rt<<1|1];
mark[rt]=mark[rt<<1]&&mark[rt<<1|1];//当他们的儿子节点都是1的时候 就不必往下更新了
}
void buildtree(int l,int r,int rt)
{
mark[rt]=0;
if(l==r)
{
scanf("%lld",&sum[rt]);
return ;
}
int m=(r+l)>>1;
buildtree(lson);
buildtree(rson);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if(r==l)//单点更新
{
sum[rt]=sqrt(sum[rt]);
if(sum[rt]<=1)
{
mark[rt]=1;
}
return ;
}
int m=(l+r)>>1;
if(L<=m&&!mark[rt<<1])//当他的儿子节点还有需要更新的时候 更新
{
update(L,R,lson);
}
if(R>m&&!mark[rt<<1|1])
{
update(L,R,rson);
}
pushup(rt);
}
long long query(int L,int R,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
return sum[rt];
}
int m=(l+r)>>1;
long long ret=0;
if(L<=m)
{
ret+=query(L,R,lson);
}
if(R>m)
{
ret+=query(L,R,rson);
}
return ret;
}
int main()
{
int n;
int ca=1;
int a,b,c;
while(scanf("%d",&n)!=EOF)
{
memset(mark,0,sizeof(mark));
memset(sum,0,sizeof(sum));
buildtree(1,n,1);
int t;
scanf("%d",&t);
printf("Case #%d:\n",ca++);
while(t--)
{
scanf("%d%d%d",&a,&b,&c);
if(b>c)//坑点  wa了一发
{
int t=c;
c=b;
b=t;
}
if(a==0)
{
update(b,c,1,n,1);
}
else
{
printf("%lld\n",query(b,c,1,n,1));
}

}
printf("\n");//坑点 ,pe了一发
}
return 0;
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: