Problem
U are given an array
A
consisting of
1≤∑A[i],N,M≤106
Approach
Since it is ensured that
∑A[i]
is no more than
106
,we suppose
f[i][j]
to be the maximum index of front of all the length-j increasing subsequences that end at i .
For example,
A[]=6,7,6,8,10
So
A[5]=4
and
f[5][3]=3
It is because that there are four length-3 increasing subsquences that end at 5(they are {6,8,10},{6,7,10},{7,8,10},{6,8,10})and the maximum index of the beginning of them is 3(it is {6,8,10}).
Of cause
f[i][j]
can be simply calculated with Segment Trees.And it is worth pointing out that u should create new points in Segment Tree only if you need because there may be lots of Segment Trees.
After solving
f[i][j]
,now we should consider how to deal with queries.Suppose our quIt is a typical way to solve problem by Binary Search.
Now we have a problem,how to check if there exists an increasing subsquence whose length is
x
in
Suppose
v
to be the maximum
But the time complexity of this approach is
O(nlog2n)
because we use Binary Search and SGT to check.
Now we consider another high-authority algorithm.There are M queries and we use Binary Search.Maybe we can get a high-authority algorithm by sorting the value of
f[i][j]
and
Li
of each query.As a matter of fact,it does work.After sorting these values in descending order,the SGT become something else.Let’s assume we still use SGT.Now when we get an
f[i][j]
,we add a tag in index i of SGT j.when we get a query
(L,R)
,we still use Binary Search and check if there are tags in a section of SGT x.Note that every time we add a tag,f[i][j]s are in descending order.That means when we get a query(L,R),the indexs of the leftmost tag in each SGT are no less than L.So we suppose
Lef[x]
to be the index of the leftmost tag in SGT x.And when we want to check a value
x
,just need to compare
The above algorithm’s time complexity is
O(nlogn)
Code
Here is my code:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
int get(){
char ch;
int s=0;
bool bz=0;
while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');
if (ch=='-')bz=1;else s=ch-'0';
while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
if (bz)return -s;
return s;
}
const int N = 1000000;
int rt[N+10],vis[N+10],tim,tot;
struct pt{
int l,r,v;
}tree[N*21+10];
int n,a[N+10],m,L[N+10],k,v[N+10],num[N+10];
int mv;
void change(int &now,int l,int r,int x,int v){
if (!now)now=++tot;
if (l==r){
tree[now].v=max(tree[now].v,v);
return;
}
int mid=(l+r)/2;
if(x<=mid)change(tree[now].l,l,mid,x,v);
else change(tree[now].r,mid+1,r,x,v);
tree[now].v=max(tree[tree[now].l].v,tree[tree[now].r].v);
}
int getv(int now,int l,int r,int x,int y){
if (!now)return 0;
if (x<=l&&r<=y)return tree[now].v;
int mid=(l+r)/2,v=0;
if (x<=mid)v=getv(tree[now].l,l,mid,x,y);
if (y>mid)v=max(v,getv(tree[now].r,mid+1,r,x,y));
return v;
}
int getmx(int now,int l,int r,int x){
if (!now)return 0;
if (r<=x)return tree[now].v;
int mid=(l+r)/2;
if (x<=mid)return getmx(tree[now].l,l,mid,x);
return max(tree[tree[now].l].v,getmx(tree[now].r,mid+1,r,x));
}
bool cmp(int x,int y){
return a[x]<a[y];
}
struct que{
int v,ty,l,w;
friend bool operator < (que a,que b){
if (a.v!=b.v)return a.v>b.v;
return a.ty<b.ty;
}
}q[N*2+10];
int lef[N+10];
int ans[N+10];
int main(){
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
int t=get();
fo(cas,1,t){
n=get();m=get();
tim++;tot=k=0;
mv=0;
fo(i,1,n){
a[i]=get();
num[i]=i;
}
sort(num+1,num+1+n,cmp);
int kk=0,lst=0;
fo(i,1,n){
if (a[num[i]]>lst){
kk++;
lst=a[num[i]];
}
a[num[i]]=kk;
}
fo(i,1,n){
L[i]=k+1;
v[k+1]=i;
fo(j,2,a[i]){
v[k+j]=0;
if (vis[j-1]<tim)continue;
v[k+j]=getmx(rt[j-1],1,kk,a[i]-1);
}
fo(j,1,a[i])
if (v[k+j]){
mv=max(mv,j);
if(vis[j]<tim){rt[j]=0;vis[j]=tim;}
change(rt[j],1,kk,a[i],v[k+j]);
}
k+=a[i];
}
fo(i,1,tot)tree[i].l=tree[i].r=tree[i].v=0;
fo(i,1,mv)rt[i]=0;
k=0;
fo(i,1,n){
fo(j,1,a[i])
if (v[L[i]+j-1]){
q[++k].v=v[L[i]+j-1];
q[k].ty=1;
q[k].l=j;
q[k].w=i;
}
}
fo(i,1,m){
int l=get(),r=get();
q[++k].v=l;
q[k].ty=2;
q[k].w=r;
q[k].l=i;
}
sort(q+1,q+1+k);
tim++;
fo(i,1,k)
if (q[i].ty==1){
if (vis[q[i].l]<tim){
vis[q[i].l]=tim;
lef[q[i].l]=N;
}
lef[q[i].l]=min(lef[q[i].l],q[i].w);
}
else{
int L=1,R=mv,va=0;
while(L<=R){
int mid=(L+R)/2;
if (vis[mid]==tim&&lef[mid]<=q[i].w){
va=mid;
L=mid+1;
}
else R=mid-1;
}
ans[q[i].l]=va;
}
fo(i,1,m)printf("%d\n",ans[i]);
}
return 0;
}