bzoj 3173: [Tjoi2013]最长上升子序列

这个题一开始感觉是想的差不多了,,然而不知道为什么没继续想(貌似是没考虑到treap的插入改怎么搞之类的)

那么这个题直接蹩脚的用treap模拟一下插入,然后枚举答案,在序列里二分就好了,最后答案就是max(ans[i],ans[i-1])(后面肯定不能比前面小吧)

 1 #include <bits/stdc++.h>
 2 #define LL long long
 3 #define inf 0x3f3f3f3f
 4 using namespace std;
 5 inline int ra()
 6 {
 7     int x=0,f=1; char ch=getchar();
 8     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
 9     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
10     return x*f;
11 }
12 int n,sz,root,now,mx;
13 int mn[100005],ans[100005];
14 int v[100005],size[100005],rnd[100005],ls[100005],rs[100005];
15 void update(int x){size[x]=size[ls[x]]+size[rs[x]]+1;}
16 void rturn(int &x){int t=ls[x]; ls[x]=rs[t]; rs[t]=x; update(x); update(t); x=t;}
17 void lturn(int &x){int t=rs[x]; rs[x]=ls[t]; ls[t]=x; update(x); update(t); x=t;}
18 void insert(int &k, int x)
19 {
20     if (!k){
21         k=++sz; size[k]=1; rnd[k]=rand();
22         return;
23     }
24     size[k]++;
25     if (size[ls[k]]<x) 
26     {
27         insert(rs[k],x-size[ls[k]]-1);
28         if (rnd[rs[k]]<rnd[k]) lturn(k);
29     }
30     else
31     {
32         insert(ls[k],x);
33         if (rnd[ls[k]]<rnd[k]) rturn(k);
34     }
35 }
36 void dfs(int x)
37 {
38     if (!x) return;
39     dfs(ls[x]);
40     v[++now]=x;
41     dfs(rs[x]);
42 }
43 void solve()
44 {
45     memset(mn,127,sizeof(mn));
46     mn[0]=-inf;
47     for (int i=1; i<=n; i++)
48     {
49         int t=upper_bound(mn,mn+mx+1,v[i])-mn;
50         if (mn[t-1]<=v[i])
51         {
52             mn[t]=min(mn[t],v[i]);
53             ans[v[i]]=t;
54             mx=max(t,mx);
55         }
56     }
57 }
58 int main(int argc, char const *argv[])
59 {
60     n=ra();
61     for (int i=1; i<=n; i++) insert(root,ra());
62     dfs(root);
63     solve();
64     for (int i=1; i<=n; i++)
65     {
66         ans[i]=max(ans[i-1],ans[i]);
67         printf("%d
",ans[i]);
68     }
69     return 0;
70 }
原文地址:https://www.cnblogs.com/ccd2333/p/6511956.html