HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)
Attack
Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 2523 Accepted Submission(s): 805
During the war, it is very important to understand the situation of both self and the enemy. So the commanders of American want to know how much time some part of the wall is successfully attacked. Successfully attacked means that the attack is not defended by the shield.
The first line of each test case is three integers, N, Q, t, the length of the wall, the number of attacks and queries, and the time each shield needs to cool down.
The next Q lines each describe one attack or one query. It may be one of the following formats
1. Attack si ti
Al Qaeda attack the wall from si to ti, inclusive. 1 ≤ si ≤ ti ≤ N
2. Query p
How many times the pth unit have been successfully attacked. 1 ≤ p ≤ N
The kth attack happened at the kth second. Queries don’t take time.
1 ≤ N, Q ≤ 20000
1 ≤ t ≤ 50
题目链接:HDU 4031
思路就是用线段树统计所有的攻击次数,再暴力统计防御次数,两者相减就是被攻击的次数,前面比较简单,后面怎么弄呢?建立数组pre[]代表上一次询问所防御到的位置,因此每一次统计的区间是上次询问时间到此次询问时间,这样可以达到不重复的统计,然后用数组d[]统计当前询问时的成功防御次数……
题目的时间轴应该是物理意义上的第k秒末而不是第k秒内,即某一秒是指一个瞬间而不是一个区间。因此实际冷却时间为t-1秒
就像这样:|____|____|____|____| 而不是 |____|____|____|____|
1 2 3 4 5 1 2 3 4
由于记录攻击的数组下标从0开始,因此每一次查询范围是 [pre[x],cnt)
线段树代码:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<bitset>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0); const int N=20010;
struct seg
{
int l,mid,r;
int sum,add;
};
seg T[N<<2];
int n,q,t; void pushup(int k)
{
T[k].sum=T[LC(k)].sum+T[RC(k)].sum;
}
void pushdown(int k)
{
if(T[k].add)
{
T[LC(k)].add+=T[k].add;
T[LC(k)].sum+=T[k].add*(T[LC(k)].r-T[LC(k)].l+1);
T[RC(k)].add+=T[k].add;
T[RC(k)].sum+=T[k].add*(T[RC(k)].r-T[RC(k)].l+1);
T[k].add=0;
}
}
void build(int k,int l,int r)
{
T[k].l=l;
T[k].r=r;
T[k].mid=MID(l,r);
T[k].add=T[k].sum=0;
if(l==r)
return ;
else
{
build(LC(k),l,T[k].mid);
build(RC(k),T[k].mid+1,r);
pushup(k);
} }
void update(int k,int l,int r,int val)
{
if(r<T[k].l||l>T[k].r)
return ;
if(l<=T[k].l&&r>=T[k].r)
{
T[k].add+=val;
T[k].sum+=val*(T[k].r-T[k].l+1);
}
else
{
pushdown(k);
update(LC(k),l,r,val);
update(RC(k),l,r,val);
pushup(k);
}
}
int query(int k,int x)
{
if(T[k].l==T[k].r&&T[k].l==x)
return T[k].sum;
pushdown(k);
if(x<=T[k].mid)
return query(LC(k),x);
else if(x>T[k].mid)
return query(RC(k),x);
}
pii range[N];
int pre[N];
int d[N];
int main(void)
{
int l,r,i,x,cur;
int tcase;
char ops[8];
scanf("%d",&tcase);
for (int c=1; c<=tcase; ++c)
{
int cnt=0;
CLR(pre,0);
CLR(d,0);
scanf("%d%d%d",&n,&q,&t);
build(1,1,n);
printf("Case %d:\n",c);
while (q--)
{
scanf("%s",ops);
if(ops[0]=='A')
{
scanf("%d%d",&l,&r);
update(1,l,r,1);
range[cnt++]=pii(l,r);
}
else
{
scanf("%d",&x);
int total=query(1,x);
for (cur=pre[x]; cur<cnt; )//范围就是上一次询问时间pre[x]到此次询问时间cnt
{
if(range[cur].first<=x&&x<=range[cur].second)
{
++d[x];
pre[x]=cur+t;//最近询问时间更新
cur+=t;//在此之后的t-1个都会防御失败,跳到第cur+t个
}
else
++cur;
}
printf("%d\n",total-d[x]);
}
}
}
return 0;
}
树状数组:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<bitset>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0); const int N=20010;
int T[N];
void add(int k,int val)
{
while (k<N)
{
T[k]+=val;
k+=(k&-k);
}
}
int getsum(int k)
{
int r=0;
while (k)
{
r+=T[k];
k-=(k&-k);
}
return r;
}
pii range[N];
int pre[N];
int d[N];
int n,q,t;
int main(void)
{
int l,r,i,x,cur;
int tcase;
char ops[8];
scanf("%d",&tcase);
for (int c=1; c<=tcase; ++c)
{
int cnt=0;
CLR(pre,0);
CLR(d,0);
CLR(T,0);
scanf("%d%d%d",&n,&q,&t);
printf("Case %d:\n",c);
while (q--)
{
scanf("%s",ops);
if(ops[0]=='A')
{
scanf("%d%d",&l,&r);
add(l,1);
add(r+1,-1);
range[cnt++]=pii(l,r);
}
else
{
scanf("%d",&x);
int total=getsum(x);
for (cur=pre[x]; cur<cnt; )//范围就是上一次询问时间pre[x]到此次询问时间cnt
{
if(range[cur].first<=x&&x<=range[cur].second)
{
++d[x];
pre[x]=cur+t;//询问时间更新
cur+=t;//在此之后的t-1个都会防御失败,跳到第cur+t个
}
else
++cur;
}
printf("%d\n",total-d[x]);
}
}
}
return 0;
}
HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)的更多相关文章
- 【poj2155】Matrix(二维树状数组区间更新+单点查询)
Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...
- NBOJv2 1050 Just Go(线段树/树状数组区间更新单点查询)
Problem 1050: Just Go Time Limits: 3000 MS Memory Limits: 65536 KB 64-bit interger IO format: % ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- hdu1556 树状数组区间更新单点查询板子
就是裸的区间更新: 相对于直观的线段树的区间更新,树状数组的区间更新原理不太相同:由于数组中的一个结点控制的是一块区间,当遇到更新[l,r]时,先将所有能控制到 l 的结点给更新了,这样一来就是一下子 ...
- HDU 1556 Color the ball (树状数组 区间更新+单点查询)
题目链接 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽&quo ...
- 【树状数组区间修改单点查询+分组】HDU 4267 A Simple Problem with Integers
http://acm.hdu.edu.cn/showproblem.php?pid=4267 [思路] 树状数组的区间修改:在区间[a, b]内更新+x就在a的位置+x. 然后在b+1的位置-x 树状 ...
- 【树状数组区间修改单点查询】HDU 4031 Attack
http://acm.hdu.edu.cn/showproblem.php?pid=4031 [题意] 有一个长为n的长城,进行q次操作,d为防护罩的冷却时间,Attack表示区间a-b的墙将在1秒后 ...
- hdu-3584 Cube---三维树状数组+区域更新单点查询
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3584 题目大意: 给定一个N*N*N多维数据集A,其元素是0或是1.A[i,j,k]表示集合中第 i ...
- POJ 2155 Matrix(二维树状数组+区间更新单点求和)
题意:给你一个n*n的全0矩阵,每次有两个操作: C x1 y1 x2 y2:将(x1,y1)到(x2,y2)的矩阵全部值求反 Q x y:求出(x,y)位置的值 树状数组标准是求单点更新区间求和,但 ...
随机推荐
- 高阶函数复习:利用reduce和map把字符串转为数字
复习高阶函数的时候,有一道题想了半天解不出来.看了下别人的解法,发现学习编程,思维真的很重要. 习题: 利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数1 ...
- java基础知识回顾之java Thread类学习(十二)-- 线程中断
官方文档翻译: 如果本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), ...
- UML中的stereotype
在使用rose的时候.rose的类里面有个stereotype的选项.选择了不同的选项类会呈现不同的图形效果.这里对stereotype做一点总结, Stereotyp英文的原意是印刷中的铅字.比如, ...
- html 表单 dom 注意跟表单的name值一致
html 表单 dom 注意跟表单的name值一致 <script type="text/javascript"> function checkForm() { var ...
- Sonar+Hudson+Maven构建系列之二:迁移Sonar
摘要:由于昨天在一台机器上安装的东西太多了,导致Linux机器上非常卡,一台Linux负担了jira, fisheye, confluence, sonar, hudson, mysql 等等,本来已 ...
- Java判断文件编码格式
转自:http://blog.csdn.net/zhangzh332/article/details/6719025 一般情况下我们遇到的文件编码格式为GBK或者UTF-8.由于中文Windows默认 ...
- SQLite使用方法 SQLiteOpenHelper操作(转)
SQLiteOpenHelper主要用于 创建数据库 SQLiteDatabase 主要用于 执行sql语句 程序内使用SQLite数据库是通过SQLiteOpenHelper进行操作 1. ...
- 【JSP jstl c标签】使用c:foreach 报错(警告)”test does not support runtime expressions“
后台封装的数据是个list,传递给前台,显示如下: <c:forEach items="${userInfo}" var="user"> 用户Nam ...
- 安装phpmyadmin
1.查看PHP版本 新建文本文档,填写下面内容: <?phpphpinfo();?>保存,然后更改文件名为phpinfo.php放到你域名根目录,然后通过你的域名+phpinfo.php浏 ...
- 克隆或拷贝的VMware虚拟机IP问题解决
克隆的虚拟机或是将虚拟机通过快照回到过去某个状态后,会上不了网. 如果不想看细节,可直接跳到小结部分. 问题描述: 运行service network restart时 Device eth0 doe ...