哈理工OJ 1161 Leyni(线段树)

Leyni
Time Limit: 3000 MS Memory Limit: 65536 K
Total Submit: 499(107 users) Total Accepted: 151(97 users) Rating:  Special Judge: No
Description

Leyni被人掳走,身在水深火热之中...
小奈叶为了拯救Leyni,独自一人前往森林深处从静竹手中夺回昏迷中的Leyni。
历经千辛万苦,小奈叶救出了Leyni,但是静竹为此极为恼怒,决定对他们发起最强烈的进攻。
不过小奈叶有一个叫做能量保护圈的道具,可以保护他们。
这个保护圈由n个小的小护盾围成一圈,从1到n编号。当某一块小护盾受到攻击的时候,小护盾就会抵消掉这次攻击,也就是说对这一块小护盾的攻击是无效攻击,从而保护圈里的人,不过小护盾在遭到一次攻击后,需要t秒进行冷却,在冷却期间受到的攻击都是有效攻击,此时他们就会遭到攻击, 即假设1秒时受到攻击并成功防御,到1+t秒时冷却才结束并能进行防御,在2到t受到的都是有效攻击。

现在小奈叶专心战斗,Leyni昏迷,他们无法得知小护盾遭受的有效攻击次数,他们需要你的帮助。
只要能帮到他们,Leyni就会赠送出一份小奈叶写真集。
哈理工OJ 1161 Leyni(线段树)_第1张图片
Input

第一行是一个整数T,表示有多少组测试数据。
第一行是三个整数,n,q,t,n表示保护圈的长度,q表示攻击的询问的总次数,t表示能量盾的冷却时间。
接下来的q行,每行表示受到的攻击或者她询问某范围内的能量盾被攻击的次数。
攻击:
Attack   a
表示编号为a的小护盾受到一次攻击, 保证 1 <= a <= n
询问:
Query  a  b
表示询问编号从a到b的小护盾(包括a和b)总共受到了多少次有效攻击。保证 1<=a,b<=n
第k次攻击发生在第k秒,询问不花费时间。
1 <= n,q <=100000
1 <= t <= 50。

Output

每一组测试数据,先输出一行"Case i:",i表示第i组测试数据,从1开始计数。
之后对于每一个询问,输出该范围内的小护盾受到的有效攻击次数,一个询问一行。

Sample Input

1
4 7 3
Attack 1
Attack 1
Attack 1
Attack 2
Attack 2
Query 1 4
Query 1 1

Sample Output

Case 1:
3
2


题目并不难,开始的时候想的复杂些,不过这里有个坑:查询操作不占CD时间(这里玩游戏的应该明白啥叫CD吧~),也就是说,查询操作不占回合数。。。。

多组操作,多组求和,线段树无疑~。不过好像理工的sharecodes里边都是用树状数组过的。这里表示没有喜欢线段树的小伙伴吗?

不多啰嗦了这里详解思路:

我们这里用一个一维数组表示护盾冷却好的时间。初始化为0.

每一次Attack的时候,回合数要+1;

如果回合数<护盾冷却好的时间,说明这里冷却还没缓好,说明算是一次有效攻击,所以要在对应点上update。

否则,回合数>护盾冷却好的时间的时候,说明这里冷却已经缓好了,不算是一次有效攻击,这个时候更新冷却时间。具体操作如下:

        for(int i=1;i<=q;i++)
        {
            char op[50];
            scanf("%s",op);
            if(op[0]=='Q')//查询操作。
            {
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%d\n",Query(x,y,1,n,1));
            }
            if(op[0]=='A')//攻击操作。
            {
                huihe++;
                int x;
                scanf("%d",&x);
                if(huihe<hudun[x])//如果回合数小于冷却时间,有效攻击一次。
                {
                    update(x,1,1,n,1);
                }
                else
                {
                    hudun[x]=huihe+t;//相反的,不算做有效攻击,并且更新冷却时间。
                }
            }
        }
然后上完整的AC代码:

#include<stdio.h>
#include<string.h>
using namespace std;
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int hudun[100050];
int tree[100050*8];
void pushup(int rt)
{
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
int Query(int L,int R,int l,int r,int rt)//区间求和
{
    if(L<=l&&r<=R)
    {
        return tree[rt];
    }
    else
    {
        int m=(l+r)>>1;
        int ans=0;
        if(L<=m)
        {
            ans+=Query(L,R,lson);
        }
        if(m<R)
        {
            ans+=Query(L,R,rson);
        }
        return ans;
    }
}
void update(int p,int c,int l,int r,int rt)//p位子,c数据.//+c次有效攻击,这里c==1
{
    //printf("%d %d %d %d %d\n",p,c,l,r,rt);
    if(l==r)
    {
        tree[rt]+=c;
    }
    else
    {
        int m=(l+r)>>1;
        if(p<=m) update(p,c,lson);
        else  update(p,c,rson);
        pushup(rt);
		//printf("sum[%d]:%d\n",rt,tree[rt]);
    }
}
void build( int l ,int r , int rt )//建树
{
	if( l == r )
	{
		tree[rt]=0;//初始化有效攻击次数为0
		return ;
	}
	else
	{
		int m = (l+r)>>1 ;
		build(lson) ;
		build(rson) ;
		pushup(rt) ;
	}
}
int main()
{
    int t;
    int kase=0;
    scanf("%d",&t);
    while(t--)
    {
        int n,q,t;
        memset(tree,0,sizeof(tree));
        memset(hudun,0,sizeof(hudun));//这里是必要的
        scanf("%d%d%d",&n,&q,&t);
        build(1,n,1);
        int huihe=0;
        printf("Case %d:\n",++kase);
        for(int i=1;i<=q;i++)
        {
            char op[50];
            scanf("%s",op);
            if(op[0]=='Q')
            {
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%d\n",Query(x,y,1,n,1));
            }
            if(op[0]=='A')
            {
                huihe++;
                int x;
                scanf("%d",&x);
                if(huihe<hudun[x])
                {
                    update(x,1,1,n,1);
                }
                else
                {
                    hudun[x]=huihe+t;
                }
            }
        }
    }
}









你可能感兴趣的:(线段树,1161,1161,1161,哈理工oj,哈理工ACM)