#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<cstring>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int M=2*1e5+20;
typedef struct
{
int op,id;
}PP;
PP p[M];
typedef struct
{
int st,End,id;
}OP;
OP ad[M];
typedef struct
{
int num,id;
}Trans;
Trans tr[2*M];
bool cmp(const Trans&a,const Trans&b)
{
return a.num<b.num;
}
int del[M];
int start[M*2],eend[2*M];
void add(int n,int x,int *s)
{
while(n<2*M)
{
s[n]+=x;
n+=n&(-n);
}
}
int getsum(int n,int *s)
{
int sum=0;
while(n>=1)
{
sum+=s[n];
n-=n&(-n);
}
return sum;
}
int main()
{
int n,T=1;
while(~scanf("%d",&n))
{
memset(start,0,sizeof(start));
memset(eend,0,sizeof(eend));
int i, t=0,s=1,ff,b;
for(i=1;i<=n;i++)
{
scanf("%d%d",&ff,&b);
if(ff==0)
{
++t;
p[i].id=t;
p[i].op=0;
tr[2*t-1].num=b;
tr[2*t-1].id=t;
tr[2*t].num=b+t;
tr[2*t].id=-1*t;
}
else
{
p[i].id=s;
p[i].op=1;
del[s++]=b;
}
}
sort(tr+1,tr+1+2*t,cmp);
int tt=1,temp=tr[1].num;
for(i=1;i<=t*2;i++)
{
if(temp<tr[i].num)
{
tt++;
temp=tr[i].num;
}
if(tr[i].id>0)
{
ad[tr[i].id].st=tt;
ad[tr[i].id].id=tr[i].id;
}
else
{
ad[tr[i].id*(-1)].End=tt;
ad[tr[i].id*(-1)].id=tr[i].id*(-1);
}
}
printf("Case #%d:\n",T++);
for(int i=1;i<=n;i++)
{
int d=p[i].id;
if(p[i].op==0)
{
int st=ad[d].st,ed=ad[d].End,sum1=0,sum2=0;
add(st,1,start);
add(ed,1,eend);
sum1=getsum(2*M-1,start)-getsum(st-1,start);
sum2=getsum(2*M-1,eend)-getsum(ed,eend);
printf("%d\n",sum1-1-sum2);
}
else
{
int s=del[d];
int st=ad[s].st,ed=ad[s].End;
add(st,-1,start);
add(ed,-1,eend);
}
}
}
return 0;
}
hdu5372(樹狀數組)
開始看這題時以爲是線段樹區間更新,誤以爲和poj2528差不多,然後上手打了。。。到末尾時發現有個點不一樣,那就是刪除,還要恢復到之前的狀態,這個不會了。又從樹狀數組入手,發現用樹狀數組很簡單。這題的主要思想,求得左端點大於等於左端點的線段的個數,然後再求得右端點大於該線段右端點的個數,然後兩數相減得出答案,用兩個樹狀數組維護即得到答案
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.