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

来源:互联网 发布:网约车用什么软件好 编辑:程序博客网 时间:2024/06/04 19:38

Can you answer these queries?

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 11957 Accepted Submission(s): 2833

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 our secret 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 of the 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.

Input
The 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 263.
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 query of the commander which ask for the sum of the endurance value of the battleship between X-th and Y-th, inclusive.

Output
For 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

Source
The 36th ACM/ICPC Asia Regional Shanghai Site —— Online Contest

来源:第三十六届ACM亚洲区域赛上海站网络赛(最简单的一道)

题意:多组输入,第一行给出N,代表有N个数,接下来一行是N个数,第三行给出M,代表有M此操作。接下来M行,每行三个数T,X,Y,T=1时,输出X到Y区间的所有数的和,T=0时X到Y区间的每一个数都变成对自己开平方并向下取整的数。

优化:有的数已经变成1了,就不用再对它操作了。
还有两处坑点,XY的大小未定,每组数据最后还要输出空行
代码

#include<stdio.h>#include<iostream>#include<algorithm>#include<string.h>#include<math.h>using namespace std;const int maxn=100005;//最大数据数量int N;//数据数量int M;//操作次数long long int sum[maxn<<2];//root区间对应数总和为sum[root]void Push_Up(int root)//数据上浮{    sum[root]=sum[root<<1]+sum[root<<1|1];}void Build(int root,int left,int right){    if(left==right)    {        scanf("%I64d",&sum[root]);        return;    }    int mid=(left+right)>>1;    Build(root<<1,left,mid);    Build(root<<1|1,mid+1,right);    Push_Up(root);}long long int Query(int root,int left,int right ,int find_left,int find_right){    if(left>=find_left&&right<=find_right)        return sum[root];    int mid=(left+right)>>1;    if(find_right<=mid)        return Query(root<<1,left,mid,find_left,find_right);    else if(find_left>mid)        return Query(root<<1|1,mid+1,right,find_left,find_right);    else        return Query(root<<1,left,mid,find_left,mid)+Query(root<<1|1,mid+1,right,mid+1,find_right);}void Update(int root,int left,int right,int find_left,int find_right){    if(left==right)    {        sum[root]=(long long int)sqrt(sum[root]);        return;    }    if(left>=find_left&&right<=find_right&&sum[root]==right-left+1)    {        return;//这里有优化,如果root对应区间内所有数都不需要开方了,直接return    }    int mid=(left+right)>>1;    if(find_right<=mid)        Update(root<<1,left,mid,find_left,find_right);    else if(find_left>mid)        Update(root<<1|1,mid+1,right,find_left,find_right);    else    {        Update(root<<1,left,mid,find_left,mid);        Update(root<<1|1,mid+1,right,mid+1,find_right);    }    Push_Up(root);}int main(){    int casen=1;//应题意要求    while(~scanf("%d",&N))//数据数量    {        Build(1,1,N);        scanf("%d",&M);        printf("Case #%d:\n",casen++);        while(M--)//M次操作        {            int T,x,y;//含义如题            int X,Y;            scanf("%d%d%d",&T,&x,&y);            X=min(x,y);//这里是个坑点            Y=max(x,y);            if(T==1)                printf("%I64d\n",Query(1,1,N,X,Y));            else                Update(1,1,N,X,Y);        }        printf("\n");//这也是个坑点!    }    return 0;}
0 0
原创粉丝点击