HDU5141--LIS again (LIS变形)

题意一个序列的LIS为MAX, 求连续子序列的LIS为MAX的个数。

先求出LIS,记录以a[i]结尾的LIS的长度,以及LIS起始位置(靠右的起始位置)。

然后线性扫一遍,,线段树与树状数组的差距还是蛮大的,,线段树900+MS,险些超时,而树状数组仅仅400+MS

代码里注释部分为线段树做法。

  1 #include <set>
  2 #include <map>
  3 #include <cmath>
  4 #include <ctime>
  5 #include <queue>
  6 #include <stack>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 typedef unsigned long long ull;
 16 typedef long long ll;
 17 const int inf = 0x3f3f3f3f;
 18 const double eps = 1e-8;
 19 const int maxn = 1e5+10;
 20 int seg[maxn<<2],pt[maxn<<2],a[maxn],vec[maxn],idx,n;
 21 int pos1[maxn],pos2[maxn];
 22 void hash_()
 23 {
 24     sort(vec,vec+idx);
 25     idx = unique(vec,vec+idx) - vec;
 26     for (int i = 0; i < n ;i++)
 27         a[i] = lower_bound(vec,vec+idx,a[i]) - vec + 1;
 28 }
 29 int ans,pp;
 30 /*
 31 void update(int l,int r,int pos,int x,int val,int s)
 32 {
 33     if (l == r)
 34     {
 35         if (val == seg[pos] && s > pt[pos])
 36             pt[pos] = s;
 37         if (val > seg[pos])
 38         {
 39             pt[pos] = s;
 40             seg[pos] = val;
 41         }
 42         return ;
 43     }
 44     int mid = (l + r) >> 1;
 45     if (x <= mid)
 46         update(l,mid,pos<<1,x,val,s);
 47     else
 48         update(mid+1,r,pos<<1|1,x,val,s);
 49     seg[pos] = max(seg[pos<<1],seg[pos<<1|1]);
 50     if (seg[pos<<1] > seg[pos<<1|1])
 51         pt[pos] =pt[pos<<1];
 52     if (seg[pos<<1] < seg[pos<<1|1])
 53         pt[pos] = pt[pos<<1|1];
 54     if (seg[pos<<1] == seg[pos<<1|1])
 55         pt[pos] = max(pt[pos<<1],pt[pos<<1|1]);
 56 }
 57 void query(int l,int r,int pos,int ua,int ub)
 58 {
 59     if (ub < ua)
 60         return ;
 61     if (ua <= l && ub >= r)
 62     {
 63         if (ans < seg[pos])
 64         {
 65             ans = seg[pos];
 66             pp = pt[pos];
 67         }
 68         if (ans == seg[pos] && pp < pt[pos])
 69             pp = pt[pos];
 70         return ;
 71     }
 72     int mid = (l + r) >> 1;
 73     if (ua <= mid)
 74         query(l,mid,pos<<1,ua,ub);
 75     if (ub > mid)
 76         query(mid+1,r,pos<<1|1,ua,ub);
 77 }*/
 78 inline int lowbit (int x)
 79 {
 80     return x & -x;
 81 }
 82 int c[2][maxn];
 83 void add(int x,int d,int s)
 84 {
 85     while (x <= idx)
 86     {
 87         if (c[0][x] < d)
 88         {
 89             c[0][x] = d;
 90             c[1][x] = s;
 91         }
 92         if (c[0][x] == d && c[1][x] < s)
 93         {
 94             c[1][x] = s;
 95         }
 96         x += lowbit(x);
 97     }
 98 }
 99 void query(int x)
100 {
101     while (x)
102     {
103         if (ans < c[0][x])
104         {
105             pp = c[1][x];
106             ans = c[0][x];
107         }
108         if (ans == c[0][x] && pp < c[1][x])
109         {
110             pp = c[1][x];
111         }
112         x -= lowbit(x);
113     }
114 }
115 int dp[maxn];
116 int main(void)
117 {
118     #ifndef ONLINE_JUDGE
119         freopen("in.txt","r",stdin);
120     #endif
121     while (~scanf ("%d",&n))
122     {
123         //memset(seg,0,sizeof(seg));
124         //memset(pt,0,sizeof(pt));
125         memset(c,0,sizeof(c));
126         idx = 0;
127         for (int i = 0; i < n; i++)
128         {
129             scanf("%d",a+i);
130             vec[idx++] = a[i];
131         }
132         hash_();
133         int LIS = 0;
134         for (int i = 0; i < n; i++)
135         {
136             ans = 0;
137             //query(1,n,1,1,a[i]-1);
138             query(a[i]-1);
139             dp[i] = ans + 1;
140             if (ans == 0)
141                 pos1[i] = i;
142             else
143                 pos1[i] = pp;
144            // update(1,n,1,a[i],dp[i],pos1[i]);
145            add(a[i],dp[i],pos1[i]);
146             LIS = max(dp[i],LIS);
147         }
148         int pre = n;
149         for (int i = n -1; i >= 0; i--)
150         {
151             if (dp[i] != LIS)
152                 continue;
153             pos2[i] = pre-1;
154             pre = i;
155         }
156         ll cnt = 0;
157         for (int i = 0; i < n; i++)
158         {
159             if (dp[i] != LIS)
160                 continue;
161             cnt += (ll)(pos1[i] + 1) * (pos2[i]+1-i);
162         }
163         printf("%I64d
",cnt);
164     }
165     return 0;
166 }
原文地址:https://www.cnblogs.com/oneshot/p/4151059.html