版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82501437
题解:
根据Dilworth定理,最小链覆盖=最长反链。 问题转化为求 个最小不上升序列能覆盖的最大数的个数。
利用杨氏矩阵,我们可以轻松得到这个值。 不过注意杨氏矩阵的插入是 的,这时候有个定理,就是把杨氏矩阵维护东西的大小比较方式改变一下,会得到置换原矩阵后的矩阵。
于是我们原矩阵只维护 行,查询前 行时我们只查询前 行,剩下的就是置换矩阵的某一列。 发现置换矩阵也只用维护前 行,于是结合二分即可做到 的复杂度。不过不好卡,直接暴力插入杨氏矩阵也可以通过。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
inline void W(int x) {
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while(x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}
const int N=50005, S=sqrt(N)+3;
int n,Q,a[N],ans[N*4];
struct qry {
int pos, k, id;
friend inline bool operator <(const qry &a,const qry &b) {return a.pos<b.pos;}
} q[N*4];
namespace A {
int a[S][N];
inline void ins(int v,int x=1,int y=n) {
if(x>=S) return;
y=min(y,a[x][0]);
while(y && a[x][y]<v) --y; ++y;
if(!a[x][y]) {
++a[x][0]; a[x][y]=v;
} else {
ins(a[x][y],x+1,y);
a[x][y]=v;
}
}
}
namespace B {
int a[S][N], len[N];
inline void inc(int pos) {for(int i=pos;i<=n;i+=(i&(-i))) ++len[i];}
inline int ask(int pos) {int rs=0; for(int i=pos;i;i-=(i&(-i))) rs+=len[i]; return rs;}
inline int ask(int l,int r) {return ask(r)-ask(l-1);}
inline void ins(int v,int x=1,int y=n) {
if(x>=S) return;
y=min(y,a[x][0]);
while(y && a[x][y]>=v) --y; ++y;
if(!a[x][y]) {
++a[x][0]; a[x][y]=v;
inc(y);
} else {
ins(a[x][y],x+1,y);
a[x][y]=v;
}
}
}
inline int qry(int k,int rs=0) {
if(k<S) {
for(int i=1;i<=k && A::a[i][0];i++) rs+=A::a[i][0];
} else {
for(int i=1;i<S;i++) rs+=A::a[i][0];
rs+=B::ask(S,k);
} return rs;
}
int main() {
n=rd(), Q=rd();
for(int i=1;i<=n;i++) a[i]=rd();
for(int i=1;i<=Q;i++) q[i].pos=rd(), q[i].k=rd(), q[i].id=i;
sort(q+1,q+Q+1);
for(int i=1,j=1;i<=n && j<=Q;++i) {
A::ins(a[i]); B::ins(a[i]);
while(j<=Q && q[j].pos==i) ans[q[j].id]=qry(q[j].k), ++j;
}
for(int i=1;i<=Q;i++) W(ans[i]), putchar('\n');
}