题意:
有4种操作:
0:清空所有记录
1 x y c:在x,y这个点添加一个c。
2 x y1 y2:问你从(1,y1)到(2,y2)这个区间内有多少不同的数。
3: 退出
题解:
1.vector
不知道为什么vector暴力可以过,,是不是数据的问题。直接开51个vector,查询的时候直接暴力查每个vector里是否有落在这个范围内的点:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int x,y;
};
vector<node>s[51];
int main()
{
int op,x,y1,y2,c,n=0;
while(scanf("%d",&op))
{
if(op==3)
return 0;
if(op==0)
{
for(int i=0;i<=50;i++)
s[i].clear();
}
else if(op==1)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
s[c].push_back({x,y});
}
else
{
int x,y1,y2,ans=0;
scanf("%d%d%d",&x,&y1,&y2);
for(int i=0;i<=50;i++)
{
for(int j=0;j<s[i].size();j++)
{
if(s[i][j].x<=x&&s[i][j].y>=y1&&s[i][j].y<=y2)
{
ans++;
break;
}
}
}
printf("%d\n",ans);
}
}
}
2.CDQ+线段树
好像可以直接用主席树开点的方式做线段树,但是CDQ也可以。
正常的三维CDQ,第一维是输入顺序,第二维是x从小到大归并排序,第三维注意如果用51个树状数组会MLE,TLE,暂时没找到啥方法可以用树状数组卡过去,线段树的话可以用状压维护这个区间内的值,因为只有51种值,那么用(1<<c)表示是否有这个值,区间不同数的话只需要位或操作即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=150005;
struct node
{
int op,x,y1,y2,id;
ll c;
}q[N],tmp[N];
int a[N*2];
int op,n=0,all=0,que=0;
ll ans[N],num[N*4];
void update(int l,int r,int root,int pos,int o,ll val)
{
if(l==r)
{
if(o==1)
num[root]|=(1ll<<val);
else
num[root]=0;
return ;
}
int mid=l+r>>1;
if(mid>=pos)
update(l,mid,root<<1,pos,o,val);
else
update(mid+1,r,root<<1|1,pos,o,val);
num[root]=num[root<<1]|num[root<<1|1];
}
ll query(int l,int r,int root,int ql,int qr)
{
if(l>=ql&&r<=qr)
return num[root];
int mid=l+r>>1;
ll ans=0;
if(mid>=ql)
ans=ans|query(l,mid,root<<1,ql,qr);
if(mid<qr)
ans=ans|query(mid+1,r,root<<1|1,ql,qr);
return ans;
}
void CDQ(int l,int r)
{
if(l==r)
return ;
int mid=l+r>>1;
CDQ(l,mid),CDQ(mid+1,r);
int p1=l,p2=mid+1,t=0;
while(p1<=mid&&p2<=r)
{
if(q[p1].x<=q[p2].x)
{
if(q[p1].op==1)
update(1,all,1,q[p1].y1,1,q[p1].c);
tmp[++t]=q[p1],p1++;
}
if(q[p1].x>q[p2].x)
{
if(q[p2].op==2)
ans[q[p2].id]|=query(1,all,1,q[p2].y1,q[p2].y2);
tmp[++t]=q[p2],p2++;
}
}
while(p1<=mid)
tmp[++t]=q[p1++];
while(p2<=r)
{
if(q[p2].op==2)
ans[q[p2].id]|=query(1,all,1,q[p2].y1,q[p2].y2);
tmp[++t]=q[p2],p2++;
}
for(int i=1;i<=t;i++)
{
q[l+i-1]=tmp[i];
if(tmp[i].op==1)
update(1,all,1,tmp[i].y1,-1,tmp[i].c);
}
}
int main()
{
while(scanf("%d",&op))
{
if(op==3)
{
sort(a+1,a+1+all);
all=unique(a+1,a+1+all)-a-1;
for(int i=1;i<=n;i++)
{
q[i].y1=lower_bound(a+1,a+1+all,q[i].y1)-a;
if(q[i].op==2)
q[i].y2=lower_bound(a+1,a+1+all,q[i].y2)-a;
}
CDQ(1,n);
for(int i=1;i<=que;i++)
{
int sum=0;
for(ll j=0;j<=50;j++)
if((ans[i]&(1ll<<j)))
sum++;
printf("%d\n",sum);
ans[i]=0;
}
n=all=que=0;
return 0;
}
if(op==0)
{
if(!all)
continue;
sort(a+1,a+1+all);
all=unique(a+1,a+1+all)-a-1;
for(int i=1;i<=n;i++)
{
q[i].y1=lower_bound(a+1,a+1+all,q[i].y1)-a;
if(q[i].op==2)
q[i].y2=lower_bound(a+1,a+1+all,q[i].y2)-a;
}
CDQ(1,n);
for(int i=1;i<=que;i++)
{
int sum=0;
for(ll j=0;j<=50;j++)
if((ans[i]&(1ll<<j)))
sum++;
printf("%d\n",sum);
ans[i]=0;
}
n=all=que=0;
continue;
}
if(op==1)
{
scanf("%d",&q[++n].x);
scanf("%d",&q[n].y1);
scanf("%lld",&q[n].c);
q[n].op=1,a[++all]=q[n].y1;
}
else if(op==2)
{
scanf("%d",&q[++n].x);
scanf("%d",&q[n].y1);
scanf("%d",&q[n].y2);
q[n].op=2;
a[++all]=q[n].y1,a[++all]=q[n].y2,q[n].id=++que;
}
}
}