Can you answer these queries?

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

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

之前听说过很多神级线段树的题,最后都是暴力拼循环节,今天难得见一个入门级别的,也算涨姿势了~

题意:给定n个数(1~100000),两种操作(1~100000)0 or 1 ,0操作是把给定区间内的数都变成原来的开方(向下取整),1操作,询问区间内的数的总和;

突破点:所有数据和的范围是2的63此方,大神们发现开方六七次以后,这些数就都变成1了~所以就不需要再向下更新了,

那么判定不需要更新的条件就是:该节点下的区间总和与该区间长度相等,那么它们妥妥都是1了,就可以返回。

但是本题坑坑比较多~

1坑:给定区间 Xth 与 Yth大小关系不定,记得用下swap~,不然就是RE(非法访问)。

2坑 : 每组测试实例最后还需要多输出一个空行~

0.0也怪不细心~

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <climits>
#include <queue>
#define ll long long using namespace std; const int MAX = ;
ll num[MAX]; struct nodes
{
int left,right;
ll large;
} tree[MAX*]; void pushup(int root)
{
tree[root].large = tree[root*].large + tree[root*+].large;
}
void build(int root,int left,int right)
{
tree[root].left = left;
tree[root].right = right;
if(left == right)
{
tree[root].large = num[left];
return;
} int mid = (left+right)/; build(*root,left,mid);
build(*root+,mid+,right); pushup(root);
} void update(int root,int left,int right)
{
if(tree[root].large == tree[root].right - tree[root].left + )
return;
if(tree[root].right == tree[root].left)
{
tree[root].large = (ll)sqrt(tree[root].large);
return;
}
int mid = (tree[root].left+tree[root].right)/;
if(left <= mid && right > mid)
{
update(*root,left,mid);
update(*root+,mid+,right);
}
else if(left > mid)
{
update(*root+,left,right);
}
else
{
update(*root,left,right);
}
pushup(root);
} ll query(int root ,int left,int right)
{
if(tree[root].large == tree[root].right - tree[root].left + )
{
return right - left + ;
}
if(left == tree[root].left && right == tree[root].right)
{
return tree[root].large;
}
int mid = (tree[root].left+tree[root].right)/;
ll ans = ;
if(right > mid && left <= mid)
{
ans += query(*root,left,mid);
ans += query(*root+,mid+,right);
}
else if(left > mid)
{
ans += query(*root+,left,right);
}
else
{
ans += query(*root,left,right);
}
return ans;
} int main(void)
{
int i,cmd,x,y,n,q,cnt= ;
while(scanf("%d",&n) != -)
{
for(i = ; i <= n; i++)
scanf("%lld",&num[i]);
build(,,n);
scanf("%d",&q);
printf("Case #%d:\n",cnt++);
for(i = ; i <q; i++)
{
scanf("%d %d %d",&cmd,&x,&y);
if(y < x)
swap(x,y);
if(cmd)
printf("%lld\n",query(,x,y));
else
update(,x,y);
}
printf("\n");
}
return ;
}

精简版

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <climits>
#include <queue>
#define ll long long using namespace std; struct Segment_T
{
static const int MAX = 1e5+;
ll num[MAX];
struct nodes
{
int lt,rt;
ll add,sum;
} T[MAX*]; Segment_T(){} void pushup(int R)
{
T[R].sum = T[R<<].sum + T[R<<|].sum;
}
void pushdown(int R)
{
if(T[R].add)
{
T[R<<].add += T[R].add;
T[R<<|].add += T[R].add;
T[R<<].sum += T[R].add * (T[R<<].rt - T[R<<].lt + );
T[R<<|].sum += T[R].add * (T[R<<|].rt - T[R<<|].lt + );
T[R].add = ;
}
}
void build(int R,int lt,int rt)
{
T[R].lt = lt;
T[R].rt = rt;
if(lt == rt)
{
T[R].sum = num[lt];
return;
}
int mid = (lt+rt)>>; build(R<<,lt,mid);
build(R<<|,mid+,rt); pushup(R);
}
void update(int R,int lt,int rt)
{
if(T[R].sum == T[R].rt - T[R].lt + )
return;
if(T[R].rt == T[R].lt)
{
T[R].sum = (ll)sqrt(T[R].sum); //返回操作处
return;
}
int mid = (T[R].lt+T[R].rt)>>;
if(lt <= mid && rt > mid)
{
update(R<<,lt,mid);
update(R<<|,mid+,rt);
}
else if(lt > mid)
update(R<<|,lt,rt);
else
update(R<<,lt,rt);
pushup(R);
}
ll query(int R,int lt,int rt)
{
if(T[R].sum == T[R].rt - T[R].lt + )
{
return rt - lt + ;
}
if(lt == T[R].lt && rt == T[R].rt)
{
return T[R].sum; //返回操作处
}
int mid = (T[R].lt+T[R].rt)>>;
ll ans = ;
if(rt > mid && lt <= mid)
ans = query(R<<,lt,mid) + query(R<<|,mid+,rt);
else if(lt > mid)
ans += query(R<<|,lt,rt);
else
ans += query(R<<,lt,rt);
return ans;
}
};
Segment_T Tr;
int main(void)
{
int i,cmd,x,y,n,q,cnt= ;
while(scanf("%d",&n) != -)
{
for(i = ; i <= n; i++)
scanf("%lld",&Tr.num[i]);
Tr.build(,,n);
scanf("%d",&q);
printf("Case #%d:\n",cnt++);
for(i = ; i <q; i++)
{
scanf("%d %d %d",&cmd,&x,&y);
if(y < x)
swap(x,y);
if(cmd)
printf("%lld\n",Tr.query(,x,y));
else
Tr.update(,x,y);
}
printf("\n");
}
return ;
}

hdu 4027 Can you answer these queries? (区间线段树,区间数开方与求和,经典题目)的更多相关文章

  1. HDU 4027—— Can you answer these queries?——————【线段树区间开方,区间求和】

    Can you answer these queries? Time Limit:2000MS     Memory Limit:65768KB     64bit IO Format:%I64d & ...

  2. HDU 4027 Can you answer these queries?(线段树区间开方)

    Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K ...

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

    https://cn.vjudge.net/problem/HDU-4027 题意 给一个有初始值的数组,存在两种操作,T=0时将[L,R]的值求平方根,T=1时查询[L,R]的和. 分析 显然不符合 ...

  4. HDU 4027 Can you answer these queries?(线段树的单点更新+区间查询)

    题目链接 题意 : 给你N个数,进行M次操作,0操作是将区间内的每一个数变成自己的平方根(整数),1操作是求区间和. 思路 :单点更新,区间查询,就是要注意在更新的时候要优化,要不然会超时,因为所有的 ...

  5. HDU 4027 Can you answer these queries【线段树】

    <题目链接> 题目大意: 给定一段序列,现在对指定区间进行两种操作:一是对指定区间进行修改,对其中的每个数字都开根号(开根号后的数字仍然取整):二是对指定区间进行查询,查询这段区间所有数字 ...

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

    给定一个长度为n的序列,m次操作. 每次操作 可以将一个区间内的所有数字变为它的根号. 可以查询一个区间内所有元素的和. 线段树的初级应用. 如果把一个区间内的元素都改为它的根号的话,是需要每个数字都 ...

  7. hdu 4027 Can you answer these queries?[线段树]

    题目 题意: 输入一个 :n  .(1<=n<<100000) 输入n个数    (num<2^63) 输入一个m :代表m个操作    (1<=m<<100 ...

  8. HDU 4027 Can you answer these queries(线段树 + 观察 )

    这题主要考察观察能力. 2^63最多只需要开7次根号就会变成1,当数字变成1之后就不需要再对其进行操作. 对于含有大于1数字的区间,向下更新. 对于数字全为1的区间,直接返回. #include &l ...

  9. SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...

  10. HDU 4027 Can you answer these queries? (线段树区间修改查询)

    描述 A lot of battleships of evil are arranged in a line before the battle. Our commander decides to u ...

随机推荐

  1. elasticsearch 中文API river

    river-jdbc 安装 ./bin/plugin --install jdbc --url http://xbib.org/repository/org/xbib/elasticsearch/pl ...

  2. href 页面跳转页面 参数

    $.getUrlParam = function (name) { var reg = new RegExp("(^|&)" + name + "=([^& ...

  3. windows 常用的快捷键

    记录一些 windows 常用快捷键,待更新 Ctrl系列 快捷键 功能 Ctrl + C 复制 Ctrl + INSERT 复制 Ctrl + V 粘贴 Ctrl + Z 撤销 Ctrl + D 删 ...

  4. Java中将字符串转为驼峰格式

    本文不再更新,可能存在内容过时的情况,实时更新请移步我的新博客:Java中将字符串转为驼峰格式: 使用CaseUtils 对Java字符串进行转换为驼峰格式: CaseUtils.toCamelCas ...

  5. parameter -- tWR

    http://www.samsung.com/global/business/semiconductor/file/product/tWR-0.pdf tWR: write recovery time ...

  6. Python快速搭建HTTP服务器

        <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style=&q ...

  7. 【codeforces 508D】Tanya and Password

    [题目链接]:http://codeforces.com/problemset/problem/508/D [题意] 给你一个字符的所有连续3个的子串; 让你复原出原串; (包含小写.大写字母以及数字 ...

  8. C++对C的扩展、增强

    C++对C的扩展 1. 双冒号::作用域运算符 代码中对同一个变量多次声明,在代码块中使用时,局部变量会将全局变量隐藏.若在代码块使用变量前添加::,表示为全局变量. ::表示作用域运算符,如常见的s ...

  9. python 日记 day4

    1.为何数据要分类 数据是用来表示状态的,不同的状态应该用不同类型的数据来表示. 2.数据类型 数字 字符串 列表 元组 字典 集合 列表:列表相比于字符串,不仅可以储存不同的数据类型,而且可以储存大 ...

  10. Ubuntu为什么远程连接不上

    因为没有安装ssh,输入以下命令, sudo apt-get install openssh-server openssh-client执行完再用xshell就可以连接上了