题目大意
有若干个区间,C(m)表示所有包含m这个点的区间编号排序后的序列。
求本质不同的非空字典序第k小的序列。
做法
先离散化,因为本质不同不会超过2n个序列。
接下来顺序扫,并维护每个位置的hash值。
遇到之前出现过的hash值就叉掉。
然后接下来枚举按字典序枚举,每次看看往字典序末尾加入i会有多少种可能。
对于k,如果它不在答案序列中,不能选择它区间所包含的m。
对于k,如果它在答案序列中,只能选择它区间所包含的m。
所以需要线段树。
还要注意每次要检查当前答案序列后面能不能不放东西了,这个也可以线段树。
#include<cstdio>
#include<algorithm>
#include<map>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100000+10,inf=10000000,mo1=1000000007,mo2=998244353;
typedef long long ll;
typedef pair<int,int> pi;
pi zlt;
map<pi,bool> s;
int father[maxn],tree[maxn][2],mic[maxn][2],ha[maxn][2],size[maxn];
int h[maxn*2],go[maxn*2],nxt[maxn*2],fx[maxn*2];
int sum[maxn*8],mi[maxn*8],ad[maxn*8];
bool bz[maxn*8];
int a[maxn],b[maxn],d[maxn*2],ans[maxn];
int i,j,k,l,r,t,n,m,tot,top,cnt,root;
bool czy;
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;
}
void add(int x,int y,int z){
go[++cnt]=y;
fx[cnt]=z;
nxt[cnt]=h[x];
h[x]=cnt;
}
void build(int p,int l,int r){
if (l==r){
sum[p]=1;
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);build(p*2+1,mid+1,r);
sum[p]=sum[p*2]+sum[p*2+1];
}
void markcl(int p){
bz[p]=1;
sum[p]=0;
mi[p]=inf;
}
void markad(int p,int v){
ad[p]+=v;
mi[p]+=v;
}
void down(int p){
if (bz[p]){
markcl(p*2);
markcl(p*2+1);
bz[p]=0;
}
if (ad[p]){
markad(p*2,ad[p]);
markad(p*2+1,ad[p]);
ad[p]=0;
}
}
void change(int p,int l,int r,int a,int b){
if (a>b) return;
if (l==a&&r==b){
markcl(p);
return;
}
down(p);
int mid=(l+r)/2;
if (b<=mid) change(p*2,l,mid,a,b);
else if (a>mid) change(p*2+1,mid+1,r,a,b);
else change(p*2,l,mid,a,mid),change(p*2+1,mid+1,r,mid+1,b);
sum[p]=sum[p*2]+sum[p*2+1];
}
int query(int p,int l,int r,int a,int b){
if (l==a&&r==b) return sum[p];
down(p);
int mid=(l+r)/2;
if (b<=mid) return query(p*2,l,mid,a,b);
else if (a>mid) return query(p*2+1,mid+1,r,a,b);
else return query(p*2,l,mid,a,mid)+query(p*2+1,mid+1,r,mid+1,b);
}
void change2(int p,int l,int r,int a,int b,int v){
if (l==a&&r==b){
markad(p,v);
return;
}
down(p);
int mid=(l+r)/2;
if (b<=mid) change2(p*2,l,mid,a,b,v);
else if (a>mid) change2(p*2+1,mid+1,r,a,b,v);
else change2(p*2,l,mid,a,mid,v),change2(p*2+1,mid+1,r,mid+1,b,v);
mi[p]=min(mi[p*2],mi[p*2+1]);
}
int pd(int x){
return tree[father[x]][1]==x;
}
void update(int x){
size[x]=size[tree[x][0]]+size[tree[x][1]]+1;
int t=((ll)ha[tree[x][0]][0]*(n+1)%mo1+x)%mo1;
t=((ll)t*mic[size[tree[x][1]]][0]%mo1+ha[tree[x][1]][0])%mo1;
ha[x][0]=t;
t=((ll)ha[tree[x][0]][1]*(n+1)%mo2+x)%mo2;
t=((ll)t*mic[size[tree[x][1]]][1]%mo2+ha[tree[x][1]][1])%mo2;
ha[x][1]=t;
}
void rotate(int x){
int y=father[x],z=pd(x);
father[x]=father[y];
if (father[y]) tree[father[y]][pd(y)]=x;
tree[y][z]=tree[x][1-z];
if (tree[x][1-z]) father[tree[x][1-z]]=y;
tree[x][1-z]=y;
father[y]=x;
update(y);
update(x);
}
void splay(int x,int y){
while (father[x]!=y){
if (father[father[x]]!=y)
if (pd(x)==pd(father[x])) rotate(father[x]);else rotate(x);
rotate(x);
}
}
void insert(int &x,int y){
if (!x){
x=y;
update(x);
return;
}
if (y<x){
insert(tree[x][0],y);
father[tree[x][0]]=x;
}
else{
insert(tree[x][1],y);
father[tree[x][1]]=x;
}
update(x);
}
int merge(int a,int b){
if (!a||!b) return a+b;
while (tree[a][1]) a=tree[a][1];
splay(a,0);
tree[a][1]=b;
father[b]=a;
update(a);
return a;
}
int main(){
freopen("list.in","r",stdin);freopen("list.out","w",stdout);
n=read();m=read();
fo(i,1,n) d[++top]=a[i]=read(),d[++top]=b[i]=read();
sort(d+1,d+top+1);
top=unique(d+1,d+top+1)-d-1;
fo(i,1,n){
a[i]=lower_bound(d+1,d+top+1,a[i])-d;
a[i]++;
b[i]=lower_bound(d+1,d+top+1,b[i])-d;
change2(1,1,top,a[i],b[i],1);
}
//change2(1,1,top,1,1,inf);
build(1,1,top);
fo(i,1,n){
add(a[i],i,1);
add(b[i]+1,i,-1);
}
mic[0][0]=mic[0][1]=1;
fo(i,1,n){
mic[i][0]=(ll)mic[i-1][0]*(n+1)%mo1;
mic[i][1]=(ll)mic[i-1][1]*(n+1)%mo2;
}
fo(i,1,top){
t=h[i];
while (t){
if (fx[t]==-1){
splay(go[t],0);
father[tree[go[t]][0]]=father[tree[go[t]][1]]=0;
root=merge(tree[go[t]][0],tree[go[t]][1]);
}
t=nxt[t];
}
t=h[i];
while (t){
if (fx[t]==1){
insert(root,go[t]);
splay(go[t],0);
root=go[t];
}
t=nxt[t];
}
if (!root) change(1,1,top,i,i);
else{
zlt=make_pair(ha[root][0],ha[root][1]);
if (s[zlt]){
change(1,1,top,i,i);
}else s[zlt]=1;
}
}
fo(i,1,n){
t=query(1,1,top,a[i],b[i]);
if (t<m){
m-=t;
change(1,1,top,a[i],b[i]);
change2(1,1,top,a[i],b[i],-1);
}
else{
ans[++tot]=i;
change(1,1,top,1,a[i]-1);
change(1,1,top,b[i]+1,top);
change2(1,1,top,a[i],b[i],-1);
if (mi[1]==0) m--;
if (m==0) break;
}
}
printf("%d\n",tot);
fo(i,1,tot) printf("%d ",ans[i]);
printf("\n");
fclose(stdin);fclose(stdout);
return 0;
}