Attack

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 2523    Accepted Submission(s): 805

Problem Description
Today is the 10th Annual of “September 11 attacks”, the Al Qaeda is about to attack American again. However, American is protected by a high wall this time, which can be treating as a segment with length N. Al Qaeda has a super weapon, every second it can attack a continuous range of the wall. American deployed N energy shield. Each one defends one unit length of the wall. However, after the shield defends one attack, it needs t seconds to cool down. If the shield defends an attack at kth second, it can’t defend any attack between (k+1)th second and (k+t-1)th second, inclusive. The shield will defend automatically when it is under attack if it is ready.

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.

 
Input
The beginning of the data is an integer T (T ≤ 20), the number of test case.
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

 
Output
For the ith case, output one line “Case i: ” at first. Then for each query, output one line containing one integer, the number of time the pth unit was successfully attacked when asked.
 
Sample Input
2
 
 
3 7 2
Attack 1 2
Query 2
Attack 2 3
Query 2
Attack 1 3
Query 1
Query 3
 
 
9 7 3
Attack 5 5
Attack 4 6
Attack 3 7
Attack 2 8
Attack 1 9
Query 5
Query 3
 
Sample Output
Case 1:
0
1
0
1
Case 2:
3
2
 

题目链接: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(线段树/树状数组区间更新单点查询+暴力)的更多相关文章

  1. 【poj2155】Matrix(二维树状数组区间更新+单点查询)

    Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...

  2. NBOJv2 1050 Just Go(线段树/树状数组区间更新单点查询)

    Problem 1050: Just Go Time Limits:  3000 MS   Memory Limits:  65536 KB 64-bit interger IO format:  % ...

  3. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  4. hdu1556 树状数组区间更新单点查询板子

    就是裸的区间更新: 相对于直观的线段树的区间更新,树状数组的区间更新原理不太相同:由于数组中的一个结点控制的是一块区间,当遇到更新[l,r]时,先将所有能控制到 l 的结点给更新了,这样一来就是一下子 ...

  5. HDU 1556 Color the ball (树状数组 区间更新+单点查询)

    题目链接 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽&quo ...

  6. 【树状数组区间修改单点查询+分组】HDU 4267 A Simple Problem with Integers

    http://acm.hdu.edu.cn/showproblem.php?pid=4267 [思路] 树状数组的区间修改:在区间[a, b]内更新+x就在a的位置+x. 然后在b+1的位置-x 树状 ...

  7. 【树状数组区间修改单点查询】HDU 4031 Attack

    http://acm.hdu.edu.cn/showproblem.php?pid=4031 [题意] 有一个长为n的长城,进行q次操作,d为防护罩的冷却时间,Attack表示区间a-b的墙将在1秒后 ...

  8. hdu-3584 Cube---三维树状数组+区域更新单点查询

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3584 题目大意: 给定一个N*N*N多维数据集A,其元素是0或是1.A[i,j,k]表示集合中第 i ...

  9. POJ 2155 Matrix(二维树状数组+区间更新单点求和)

    题意:给你一个n*n的全0矩阵,每次有两个操作: C x1 y1 x2 y2:将(x1,y1)到(x2,y2)的矩阵全部值求反 Q x y:求出(x,y)位置的值 树状数组标准是求单点更新区间求和,但 ...

随机推荐

  1. Gym 100801E Easy Arithmetic (思维题)

    题目:传送门.(需要下载PDF) 题意:给定一个长度不超过1000的字符串表达式,向该表达式中加入'+'或'-',使得表达式的值最大,输出该表达式. 题解:比如300-456就改成300-4+56,遇 ...

  2. Xshell 中文乱码

    Xshell对于嵌入式开发来说,是个非常不错的工具.但或许都有过被中文显示为乱码的问题感觉有点不爽.解决方法其实很简单的,即把xshell编码方式改成UTF-8即可. [文件]–>[打开]–&g ...

  3. android 输入法出现挤压屏幕、android输入键盘覆盖了屏幕控件的解决办法

    如果希望输入法键盘弹出时不自动向上挤压activity,在Manifest清单文件中对应的activty中设置属性android:windowSoftInputMode="adjustPan ...

  4. POSIX线程

    大多数线程函数以pthread_开头,.h为pthread.h,   用-lpthread来链接线程库. 编写多线程时,定义宏_REENTRANT告诉编译器需要可重入,此宏必须位于任何#include ...

  5. hdu 4185 二分图匹配

    题意用1*2的木板覆盖矩阵中的‘#’,(木板要覆盖的只能是‘#’),问最多能用几个木板覆盖 将#抽象为二分图的点,一个木板就是一个匹配,注意最后结果要除以2 Sample Input 1 6 .... ...

  6. android开发 NDK 编译和使用静态库、动态库 (转)

    在eclipse工程目录下建立一个jni的文件夹 在jni文件夹中建立Android.mk和Application.mk文件 Android.mk文件: Android提供的一种makefile文件, ...

  7. Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2) B. Bear and Three Musketeers 枚举

                                          B. Bear and Three Musketeers                                   ...

  8. visible,invisible,gone区别

    在Android开发中,大部分控件都有visibility这个属性,其属性有3个分别为“visible ”.“invisible”.“gone”.主要用来设置控制控件的显示和隐藏.有些人可能会疑惑In ...

  9. TeeChart注册方法

  10. Eclipse开发,利用WordWrap设置自动换行

    安装 WordWrap : Help → install new Software→http://ahtik.com/eclipse-update/ 安装成功后,重启Eclipse,鼠标右键开启自动换 ...