在数轴上给你一些线段,每添加一条线段,问完全被它包含的区间的个数。
还有删除操作。线段长度是递增的。
题解用线段长度递增这个特点,可以用树状数组做,具体这样:
算出左端点比当前插入线段的左端点大的数目,再减去右端点比插入的右端点大的数目,由于线段长度是递增的,所以当前一定的答案一定是对的。
然而我用的是cdq分治的方法去做,复杂度nlogn^2,算出前面一半的线段添加对后面线段的查询的贡献减去前面一半删除线段的贡献对查询的贡献就可以了。杭电上是T了,本地跑1.6s,答案对的,排序去优化下正常就可以过了,不过懒。。。。。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <queue>
#include <map>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <set>
#include <cmath>
using namespace std;
typedef long long ll;
const int MAXN=4e5+10;
int bits[MAXN];
int L[MAXN];
int ans[MAXN];
int n;
template <class T>
inline bool scan_d(T &ret)
{
char c;
int sgn;
if(c=getchar(),c==EOF) return 0; //EOF
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}
inline void out(int x)
{
if(x>9) out(x/10);
putchar(x%10+'0');
}
inline void add(int p,int v)
{
while(p<=n)
{
bits[p]+=v;
p+=p&-p;
}
}
inline int sum(int p)
{
int ans=0;
while(p)
{
ans+=bits[p];
p-=p&-p;
}
return ans;
}
struct AP
{
int id,v,t;
bool operator <(const AP &a) const
{
if(v!=a.v) return v<a.v;
if(t==a.t)
{
if(t==0) return id>a.id;
return id<a.id;
}
return t<a.t;
}
AP() {}
AP(int _id,int _v,int _t)
{
id=_id,v=_v,t=_t;
}
} v[MAXN*2],q[MAXN*2];
int a[MAXN],b[MAXN],cnt[MAXN];
int adl[MAXN],adr[MAXN];
void cal(int l,int r)
{
if(l>=r) return ;
// cout<<l<<' '<<r<<endl;
int mid=(l+r)/2;
cal(l,mid);
cal(mid+1,r);
int k=0,c=0;
for(int i=mid+1; i<=r; i++)
{
if(a[i]) continue;
else
{
v[k++]=AP(i,adl[cnt[i]],0);
v[k++]=AP(i,adr[cnt[i]],1);
q[c++]=AP(i,adl[cnt[i]],0);
q[c++]=AP(i,adr[cnt[i]],1);
}
}
for(int i=mid; i>=l; i--)
{
if(a[i])
{
q[c++]=AP(-i,adl[b[i]],0);
q[c++]=AP(-i,adr[b[i]],1);
}
else
{
v[k++]=AP(-i,adl[cnt[i]],0);
v[k++]=AP(-i,adr[cnt[i]],1);
}
}
sort(v,v+k);
memset(bits,0,sizeof(int)*(k+1));
n=k;
for(int i=0; i<k; i++)
{
AP &x=v[i];
if(x.id>0)
{
if(x.t==0) L[x.id]=i+1;
else
ans[x.id]+=sum(L[x.id]);
}
else
{
x.id=-x.id;
if(x.t==0) L[x.id]=i+1;
else
{
add(1,1);
add(L[x.id]+1,-1);
}
}
}
sort(q,q+c);
memset(bits,0,sizeof(int)*(c+1));
n=c;
for(int i=0; i<c; i++)
{
AP &x=q[i];
if(x.id>0)
{
if(x.t==0) L[x.id]=i+1;
else
ans[x.id]-=sum(L[x.id]);
}
else
{
x.id=-x.id;
if(x.t==0) L[x.id]=i+1;
else
{
add(1,1);
add(L[x.id]+1,-1);
}
}
}
}
int main()
{
// freopen("/home/sunshine/tests/input","r",stdin);
// freopen("in","r",stdin);
// freopen("out","w",stdout);
// srand(time(NULL));
int kcase=0;
int n;
while(cin>>n)
{
// n=rand()%2+1;
int c=1;
for(int i=1; i<=n; i++)
{
// scan_d(a[i]);
// scan_d(b[i]);
scanf("%d%d",a+i,b+i);
if(a[i]==0)
{
adl[c]=b[i];
adr[c]=b[i]+c;
cnt[i]=c;
c++;
}
}
fill(ans,ans+n+1,0);
cal(1,n);
// bool xk=false;
// if(test(n)==false)
// {
// for(int i=1;i<=n;i++)
// cout<<a[i]<<' '<<b[i]<<' '<<ans[i]<<endl;
// xk=true;
// }
printf("Case #%d:\n",++kcase);
for(int i=1; i<=n; i++)
{
if(a[i]==0)
{
out(ans[i]);
putchar(10);
// printf("%d\n",ans[i]);
}
}
// if(xk) break;
}
return 0;
}