考场上用的set存储,然后就case:60%超时了。。。。用vector存可以少一个log,2900ms过得,常数还是不太好。。。我们对每个区间的左端点进行离散化,然后线段树每个叶子节点表示为左端点离散化后的值,每个点存一个vector,里面存储区间左端点在当前节点表示区间中的区间的右端点的值,那么我们对于每一个摧毁的位置pos,二分找到比pos小或等于的最近的左区间端点离散化后的值x,那么我们就去1-x这个区间中找其中存储的区间中右端点大于等于pos的那些区间,把他们删掉。我们对每个节点的vector排个序后,再进行二分操作,一个区间只在logn个节点中出现,每个点也只被删除一次,所以vector的二分复杂度是越来越小的,总复杂度就可以近似nlogn
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
#include<vector>
#define maxl 200010
#define mod 998244353
using namespace std;
int n,m,cas,res,tot,cnt,L,R,tm;
struct nb
{
int num,id,f;
bool operator < (const nb &b) const
{
return num<b.num;
}
}b[maxl];
struct ddd
{
int r,id;
bool operator < (const ddd &b) const
{
if(r==b.r)
return id<b.id;
return r<b.r;
}
};
struct dddd
{
int l,r,id;
bool operator < (const ddd &b) const
{
if(r==b.r)
return id<b.id;
return r<b.r;
}
}
a[maxl];
struct node
{
int l,r;
vector <ddd> s;
}tree[maxl<<2];
int ans[maxl];
set <ddd> ::iterator it;
bool cmp(const nb &x,const nb &y)
{
return x.num<y.num;
}
inline void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;tree[k].s.clear();
if(l==r)
return;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
inline void add(int k,ddd d)
{
tree[k].s.push_back(d);
if(tree[k].l==tree[k].r)
return;
int mid=(tree[k].l+tree[k].r)>>1;
if(L<=mid)
add(k<<1,d);
else
add(k<<1|1,d);
}
inline void sorttree(int k)
{
if(tree[k].l==tree[k].r)
return;
sort(tree[k].s.begin(),tree[k].s.end());
sorttree(k<<1);sorttree(k<<1|1);
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' &&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void prework()
{
//scanf("%d%d",&n,&m);
n=read();m=read();
for(register int i=1;i<=n;++i)
{
//scanf("%d%d",&a[i].l,&a[i].r);
a[i].l=read();a[i].r=read();
a[i].id=i;
b[i].num=a[i].l;b[i].id=i;
ans[i]=0;
}
sort(b+1,b+1+n,cmp);
cnt=1;b[1].f=cnt;
a[b[1].id].l=cnt;
for(register int i=2;i<=n;++i)
if(b[i].num==b[i-1].num)
{
a[b[i].id].l=cnt;
b[i].f=cnt;
}
else
{
++cnt;
a[b[i].id].l=cnt;
b[i].f=cnt;
}
build(1,1,cnt);
ddd d;
for(register int i=1;i<=n;++i)
{
d.r=a[i].r;d.id=a[i].id;
L=a[i].l;
add(1,d);
}
sorttree(1);
}
inline void query(int k,int pos)
{
if(L<=tree[k].l && tree[k].r<=R)
{
ddd d;d.id=0;d.r=pos;
int ind=lower_bound(tree[k].s.begin(),tree[k].s.end(),d)-tree[k].s.begin();
for(int i=ind;i<tree[k].s.size();i++)
{
int idx=tree[k].s[i].id;
if(!ans[idx])
tot++,res=(1ll*res*idx)%mod,ans[idx]=tm;
}
tree[k].s.erase(tree[k].s.begin()+ind,tree[k].s.end());
return;
}
int mid=(tree[k].l+tree[k].r)>>1;
if(R<=mid)
query(k<<1,pos);
else
if(L>mid)
query(k<<1|1,pos);
else
{
query(k<<1,pos);
query(k<<1|1,pos);
}
}
inline void mainwork()
{
printf("Case #%d:\n",cas);
int pos,x;b[0].f=0;res=0;tot=0;
for(register int i=1;i<=m;++i)
{
scanf("%d",&pos);
pos=pos^res;
nb d;d.num=pos;
x=lower_bound(b+1,b+1+n,d)-b;
if(b[x].num==pos)
x=b[x].f;
else
x=b[x-1].f;
if(x==0)
{
res=0;tot=0;
printf("%d\n",tot);
continue;
}
res=1;tot=0;
ddd desd;
tm=i;L=1;R=x;
query(1,pos);
printf("%d\n",tot);
if(tot==0)
res=0;
}
}
inline void print()
{
for(register int i=1;i<=n;++i)
printf("%d%c",ans[i],i==n?'\n':' ');
}
int main()
{
int t;
freopen("9.in","r",stdin);
freopen("9.out","w",stdout);
scanf("%d",&t);
for(cas=1;cas<=t;++cas)
{
prework();
mainwork();
print();
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
#define maxl 200010
#define mod 998244353
using namespace std;
int n,m,cas,res,tot,cnt,L,R;
struct nb
{
int num,id,f;
bool operator < (const nb &b) const
{
return num<b.num;
}
}b[maxl];
struct ddd
{
int r,id;
bool operator < (const ddd &b) const
{
if(r==b.r)
return id<b.id;
return r<b.r;
}
};
struct dddd
{
int l,r,id;
bool operator < (const ddd &b) const
{
if(r==b.r)
return id<b.id;
return r<b.r;
}
}
a[maxl];
struct node
{
int l,r;
set <ddd> s;
}tree[maxl<<2];
int ans[maxl];
set <ddd> ::iterator it;
bool cmp(const nb &x,const nb &y)
{
return x.num<y.num;
}
inline void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;tree[k].s.clear();
if(l==r)
return;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
inline void add(int k,ddd d)
{
tree[k].s.insert(d);
if(tree[k].l==tree[k].r)
return;
int mid=(tree[k].l+tree[k].r)>>1;
if(L<=mid)
add(k<<1,d);
else
add(k<<1|1,d);
}
inline void prework()
{
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;++i)
{
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id=i;
b[i].num=a[i].l;b[i].id=i;
ans[i]=0;
}
sort(b+1,b+1+n,cmp);
cnt=1;b[1].f=cnt;
a[b[1].id].l=cnt;
for(register int i=2;i<=n;++i)
if(b[i].num==b[i-1].num)
{
a[b[i].id].l=cnt;
b[i].f=cnt;
}
else
{
++cnt;
a[b[i].id].l=cnt;
b[i].f=cnt;
}
build(1,1,cnt);
ddd d;
for(register int i=1;i<=n;++i)
{
d.r=a[i].r;d.id=a[i].id;
L=a[i].l;
add(1,d);
}
}
inline ddd query(int k,int pos)
{
if(L<=tree[k].l && tree[k].r<=R)
{
ddd d;d.id=0;d.r=pos;
//it=lower_bound(tree[k].s.begin(),tree[k].s.end(),d);
it=tree[k].s.lower_bound(d);//上面那个lower_bound是O(n)的= =,改了以后从60%到了80%TLE
if(it!=tree[k].s.end())
d=(*it);
return d;
}
int mid=(tree[k].l+tree[k].r)>>1;
if(R<=mid)
return query(k<<1,pos);
else
if(L>mid)
return query(k<<1|1,pos);
else
{
ddd d=query(k<<1,pos);
if(d.id!=0)return d;
return query(k<<1|1,pos);
}
}
inline void des(int k,int l,ddd x)
{
it=tree[k].s.find(x);
tree[k].s.erase(it);
if(tree[k].l==tree[k].r)
return;
int mid=(tree[k].l+tree[k].r)>>1;
if(l<=mid)
des(k<<1,l,x);
else
des(k<<1|1,l,x);
}
inline void mainwork()
{
printf("Case #%d:\n",cas);
int pos,x;b[0].f=0;
for(register int i=1;i<=m;++i)
{
scanf("%d",&pos);
pos=pos^res;
nb d;d.num=pos;
x=lower_bound(b+1,b+1+n,d)-b;
if(b[x].num==pos)
x=b[x].f;
else
x=b[x-1].f;
if(x==0)
{
res=0;tot=0;
printf("%d\n",tot);
continue;
}
res=1;tot=0;
ddd desd;
while(1)
{
L=1;R=x;
desd=query(1,pos);
if(desd.id==0)
break;
tot++;res=(1ll*res*desd.id)%mod;
ans[desd.id]=i;
des(1,a[desd.id].l,desd);
}
printf("%d\n",tot);
if(tot==0)
res=0;
}
}
inline void print()
{
for(register int i=1;i<=n;++i)
printf("%d%c",ans[i],i==n?'\n':' ');
}
int main()
{
int t;
scanf("%d",&t);
for(cas=1;cas<=t;++cas)
{
prework();
mainwork();
print();
}
return 0;
}