Segment Game (hdu 5372 树状数组+离散化)

Segment Game

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 534    Accepted Submission(s): 132


Problem Description
Lillian is a clever girl so that she has lots of fans and often receives gifts from her fans.

One day Lillian gets some segments from her fans Lawson with lengths of 1,2,3... and she intends to display them by adding them to a number line.At the i-th add operation,she will put the segment with length of i on the number line.Every time she put the segment on the line,she will count how many entire segments on that segment.During the operation ,she may delete some segments on the line.(Segments are mutually independent)
 

Input
There are multiple test cases.

The first line of each case contains a integer n — the number of operations(1<=n<= 2105 , n <= 7105 )

Next n lines contain the descriptions of the operatons,one operation per line.Each operation contains two integers a , b. 

if a is 0,it means add operation that Lilian put a segment on the position b(|b|< 109 ) of the line.
(For the i-th add operation,she will put the segment on [b,b+i] of the line, with length of i.)

if a is 1,it means delete operation that Lilian will delete the segment which was added at the b-th add operation.
 

Output
For i-th case,the first line output the test case number.

Then for each add operation,ouput how many entire segments on the segment which Lillian newly adds.
 

Sample Input
  
  
3 0 0 0 3 0 1 5 0 1 0 0 1 1 0 1 0 0
 

Sample Output
  
  
Case #1: 0 0 0 Case #2: 0 1 0 2
Hint
For the second case in the sample: At the first add operation,Lillian adds a segment [1,2] on the line. At the second add operation,Lillian adds a segment [0,2] on the line. At the delete operation,Lillian deletes a segment which added at the first add operation. At the third add operation,Lillian adds a segment [1,4] on the line. At the fourth add operation,Lillian adds a segment [0,4] on the line
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5378  5377  5376  5374  5373 


题意:两种操作,添加线段和删除线段,第i次添加时告诉线段起点并且要添加长度为i的线段,删除第i次添加的线段,问每次添加后有多少线段是落在当前要画的线段内部的。

思路:因为每次画的线段的长度是递增的,所以当前画的线段不可能被其他线段包含,那么统计小于左端点的点的个数x和小于等于右端点的点的个数y,ans=y-x。分别用树状数组维护,没写过树状数组了,都忘了,又复习了一下。

代码:

#include <iostream>
#include <functional>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

#define INF 0x3f3f3f3f
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 400005;
const int MAXM = 200010;
const int N = 1005;

typedef pair<int,int>P;
int bit[2][MAXN];
int n;
int pos[MAXN],num;
int L[MAXN],R[MAXN],op[MAXN];
P pir[MAXN];

inline int lowbit(int x)
{
    return x&-x;
}

void add(int i,int x,int c) //c=0时表示维护的左端点,c=1时表示维护的右端点
{
    while (i<MAXN)
    {
        bit[c][i]+=x;
        i+=lowbit(i);
    }
}

int sum(int i,int c)
{
    int s=0;
    while (i>0)
    {
        s+=bit[c][i];
        i-=lowbit(i);
    }
    return s;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
#endif
    int i,j,cas=0;
    while (~scanf("%d",&n))
    {
        int tot=0;num=0;
        memset(bit,0,sizeof(bit));
        for (i=1;i<=n;i++)
        {
            scanf("%d%d",&op[i],&L[i]);
            if (op[i]==0)
            {
                R[i]=L[i]+(++tot);
                pos[num++]=L[i];
                pos[num++]=R[i];
            }
        }
        tot=0;
        sort(pos,pos+num);
        num=unique(pos,pos+num)-pos;
        for (i=1;i<=n;i++)  //离散化
        {
            if (op[i]==0)
            {
                L[i]=lower_bound(pos,pos+num,L[i])-pos+1;
                R[i]=lower_bound(pos,pos+num,R[i])-pos+1;
                pir[++tot]=make_pair(L[i],R[i]);
            }
        }
        printf("Case #%d:\n",++cas);
        for (i=1;i<=n;i++)
        {
            if (op[i]==0)
            {
                printf("%d\n",sum(R[i],1)-sum(L[i]-1,0));
                add(L[i],1,0);
                add(R[i],1,1);
            }
            else
            {
                add(pir[L[i]].first,-1,0);
                add(pir[L[i]].second,-1,1);
            }
        }
    }
    return 0;
}



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值