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)位置的值 树状数组标准是求单点更新区间求和,但 ...
随机推荐
- AJAX,JSON搜索智能提示
效果 开发结构参考AJAX,JSON用户校验 主要有两个核心文件 1,处理输入字符,进行后台搜索的servlet Suggest.java package org.guangsoft.servlet; ...
- sublime 实用 快捷键
alt+- 向后导航 alt+shift+- 向前导航 ctrl+shift+↑↓ 上下移动一行 ctrl+k,ctrl+u 转换所选为大写 ctrl+k,ctrl+l(字母L) 转换所选为小写 ct ...
- 一塔湖图(codevs 1024)
题目描述 Description 小松所在的PK大学校园又称作燕园,是一个十分美丽的校园.有博雅塔,未名湖,亚洲最大的高校图书馆,人称“一塔湖图”.但是由于燕园的历史比较悠久,所以很多的老房子都要不断 ...
- opencv学习笔记(二)寻找轮廓
opencv学习笔记(二)寻找轮廓 opencv中使用findContours函数来查找轮廓,这个函数的原型为: void findContours(InputOutputArray image, O ...
- 学习hadoop,搭建hadoop遇到一些特殊问题
我执行下面步骤: 1. 动态增加DataNode节点和TaskTracker节点 以host9为例 在host9上执行: 指定主机名 vi /etc/hostname 指定主机名到IP地址的映射 ...
- struts2升级文档
http://www.linuxdiyf.com/viewarticle.php?id=537212
- ytu 2029: C语言实验——温度转换(水题)
2029: C语言实验——温度转换 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 12 Solved: 10[Submit][Status][Web B ...
- javascript 复习代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- 网站构建学习笔记(0)——基本概念了解及资源学习(copy自w3school)
一.学习方面 1.WWW - 万维网 什么是 WWW? WWW 指万维网(World Wide Web) 万维网常被称为Web Web 是由遍布全球的计算机所组成的网络 所有 Web 中的计算机都可以 ...
- Android应用开发--MP3音乐播放器代码实现(一)
需求1:将内存卡中的MP3音乐读取出来并显示到列表当中 1. 从数据库中查询所有音乐数据,保存到List集合当中,List当中存放的是Mp3Info对象 2. 迭代List集合,把每一个Mp3 ...