BZOJ #4282. 慎二的隨機數列
阿新 • • 發佈:2020-10-07
陳指導的考試題都沒做過來補一補部落格
這題剛開始想了一個naive的做法,先找出給定位置的LIS再把任填的加上去
但這樣顯然是GG的,後來想按每個給定位置為結尾DP,想要優化到\(O(n\log n)\)就要用平衡樹優化DP
但後來再仔細一想,發現真正需要關注的不是給定的位置而是任選的位置,因為如果為了一個給定位置而放棄一些任選位置顯然是會更優的
因此我們先強制所有不給定的位置都要選,現在就是要最大化能選的給定位置的個數
考慮此時對於兩個給定的位置\(i,j\),當\(a_i+x<a_j\)這兩個數才能同時選,其中\(x\)表示\([i,j]\)中不給定的位置個數
把\(x\)用字首和\(pfx_j-pfx_i\)
#include<cstdio> #include<iostream> #include<algorithm> #define RI register int #define CI const int& using namespace std; const int N=100005; int n,a[N],x,rst[N],pfx[N],m,ans; char ch; class Tree_Array { private: int bit[N]; public: #define lowbit(x) (x&-x) inline int get(RI x,int ret=0) { for (;x;x-=lowbit(x)) ret=max(ret,bit[x]); return ret; } inline void add(RI x,CI y) { for (;x<=m;x+=lowbit(x)) bit[x]=max(bit[x],y); } #undef lowbit }BIT; int main() { //freopen("cauchy.in","r",stdin); freopen("cauchy.out","w",stdout); RI i; for (scanf("%d",&n),a[0]=-2e9,i=1;i<=n;++i) { while (ch=getchar(),ch!='N'&&ch!='K'); scanf("%d",&x); if (ch=='K') a[i]=x; else pfx[i]=1; } for (i=1;i<=n;++i) if (pfx[i]+=pfx[i-1],a[i]) rst[++m]=a[i]=a[i]-pfx[i]; for (sort(rst+1,rst+m+1),m=unique(rst+1,rst+m+1)-rst-1,i=1;i<=n;++i) if (a[i]) a[i]=lower_bound(rst+1,rst+m+1,a[i])-rst, ans=max(ans,x=BIT.get(a[i]-1)+1),BIT.add(a[i],x); return printf("%d",ans+pfx[n]),0; }