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 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 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
许多邪恶的战列舰在战斗前排成一行。我们的指挥官决定用我们的秘密武器消灭战列舰。每一艘战舰都可以被标记为耐力值。对于我们的秘密武器的每一次攻击,它都可以使战列舰的一个连续部分的忍耐力下降,使它们的忍耐力减到原来的值的平方根。在我们秘密武器的系列攻击中,指挥官想要评估武器的效果,所以他找你帮忙。
您被要求回答的问题,即耐力的总和,连续部分的战舰线。
注意,平方根操作应该四舍五入为整数。
输入
输入包含几个测试用例,由EOF终止。
对于每个测试用例,第一行包含一个整数N,表示一行中有N艘邪恶的战舰。(1 <= N <= 100000)
第二行包含N个整数Ei,表示每艘战舰从这一行的开始到结束的耐力值。你可以假设所有耐力值的总和小于2 63。
下一行包含一个整数M,表示操作和查询的数量。(1 <= M <= 100000)
对于以下M行,每一行包含3个整数T, X, y, T=0表示秘密武器的动作,这将会降低战列舰在X-th和Y-th之间的耐久值。T=1表示指挥员的询问,要求计算战舰在X-th和Y-th之间的耐久值之和。
输出
对于每个测试用例,在第一行打印用例号。然后为每个查询打印一行。并记住在每个测试用例之后跟随空行。
线段树比较经典的题目,难点是如何将其更新至平方根
还有1的平方根还是1,比较模板吧,上代码
主要的就是修改函数
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int max=100005;
static int N,M,T,X,Y;
static long[] tree=new long[max<<2];
static long[] arr=new long[max<<2];
//构造线段树,父节点为子节点的和
static void build_tree(int node,int start,int end){
if(start==end){
tree[node]=arr[start];
return;
}
int mid=(start+end)>>1;
build_tree(node<<1,start,mid);
build_tree(node<<1|1,mid+1,end);
tree[node]=tree[node<<1]+tree[node<<1|1];
return;
}
//修改X-Y变为原值的平方根
static void update_tree(int node,int start,int end,int L,int R){
//剪枝。如果区间被包含,并且区间和为区间的大小,即区间中均为1,1的平方根为1
if(L<=start&&end<=R&&tree[node]==end-start+1) return;
if(start==end){
tree[node]=(long)Math.sqrt(tree[node]); //单点修改
return;
}
int mid=(start+end)>>1;
if(R<=mid) update_tree(node<<1,start,mid,L,R);
else if(L>mid) update_tree(node<<1|1,mid+1,end,L,R);
else{
update_tree(node<<1,start,mid,L,R);
update_tree(node<<1|1,mid+1,end,L,R);
}
tree[node]=tree[node<<1]+tree[node<<1|1];//回溯更新
return;
}
static long query_tree(int node,int start,int end,int L,int R){
if(L<=start&&end<=R){
return tree[node];
}
int mid=(start+end)>>1;
if(R<=mid) return query_tree(node<<1,start,mid,L,R);
else if(L>mid) return query_tree(node<<1|1,mid+1,end,L,R);
else{
return query_tree(node<<1,start,mid,L,R)+query_tree(node<<1|1,mid+1,end,L,R);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int k=0;
while(sc.hasNext()){
Arrays.fill(tree,0);
Arrays.fill(arr,0);
k++;
N=sc.nextInt();//N艘战舰的耐久值
for(int i=1;i<=N;i++)
arr[i]=sc.nextLong();
M=sc.nextInt();
build_tree(1,1,N);//构造线段树
System.out.println("Case #"+k+":");
for(int i=0;i<M;i++){
T=sc.nextInt();
X=sc.nextInt();
Y=sc.nextInt();
if(X>Y){//这里要注意X Y的大小
int t=X;
X=Y;
Y=t;
}
if(T==0){
update_tree(1,1,N,X,Y);//修改X-Y变为原值的平方根
}else{
System.out.println(query_tree(1,1,N,X,Y));
}
}
System.out.println();
}
}
}

本文介绍了一种使用线段树算法解决战舰耐力评估问题的方法。在一个连续的战舰序列中,每次攻击都会使战舰的耐力值减少到其平方根。任务是评估一系列攻击后的战舰耐力总和,通过线段树进行高效更新和查询。
396

被折叠的 条评论
为什么被折叠?



