CF #345 Div1 D Zip-line

题目链接:http://codeforces.com/contest/650/problem/D

大意是给一个数组,若干询问,每一次把一个数字改为另一个数字,问当前数组最长上升子序列,询问之间是独立的。

 

注意到:假设初始数组的LIS长度为len。如果某一个位置的数字属于所有LIS,那么即便这个位置的数字被更改,答案至少是len-1,也有可能会因为变化维持len不变(未必是因为变化介于原来LIS前一个数字和后一个数字之间)。如果某一个位置的数字不是属于所有的LIS(属于某一种或者不属于任何LIS),那么答案至少是len,但也有可能因为变化新答案为len+1。至此,处理出所有位置的数字是否属于所有LIS的情况后,所有询问有了保底的答案。对于这两种情况,可能会产生不保底的情况,则需要对每一个询问查询,左边小于新数字的最大dp值,与右边大于新数字的最大dp值,两者相加再加上1与保底答案取最大值。具体操作,可以按照询问的位置对询问排序,离线处理。

 

具体写法有两种,一种是树状数组对原有数组数字与询问新数字全部离散化处理,以及基于LIS O(nlog(n))二分解法的写法。判断一个数字是否属于某一个LIS,条件是f[i]+g[i]==len-1? 其中f[i]和g[i]分别是以a[i]为结尾从1到i的LIS长度以及以a[i]为开端从i到n的LIS长度。判断一个数字是否属于所有LIS,则扫描所有属于某一种LIS的数字,统计它们的f值或者g值出现次数,如果某一个f值只出现了1次,则说明拥有这个f值的数字被所有LIS经过。

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <string>
  5 #include <string.h>
  6 #include <stdio.h>
  7 #include <math.h>
  8 #include <stdlib.h>
  9 #include <queue>
 10 #include <stack>
 11 #include <map>
 12 #include <set>
 13 
 14 using namespace std;
 15 
 16 const int N=1e6+12345;
 17 int a[N],b[N];
 18 struct Query {
 19     int p,v;
 20     int id;
 21     int ans;
 22     int l,r;
 23     bool operator < (const Query &o) const {
 24         return p<o.p;
 25     }
 26 }query[N];
 27 
 28 int t[N];
 29 inline int lowbit(int x) {
 30     return x&(-x);
 31 }
 32 void upd(int x,int v) {
 33     for (;x<N;x+=lowbit(x))
 34         t[x]=max(t[x],v);
 35 }
 36 int ask(int x) {
 37     int ret=0;
 38     for (;x;x-=lowbit(x))
 39         ret=max(ret,t[x]);
 40     return ret;
 41 }
 42 int lis(int n,int *f){
 43     memset(t,0,sizeof t);
 44     int ret=0;
 45     for (int i=0;i<n;i++) {
 46         int d=ask(a[i]-1);
 47         upd(a[i],d+1);
 48         f[i]=d+1;
 49         ret=max(ret,d+1);
 50     }
 51     return ret;
 52 }
 53 bool flag[N];int cnt[N];
 54 int ret[N];
 55 int f[N],g[N];
 56 int main(){
 57     int n,m;
 58     scanf("%d %d",&n,&m);
 59     for (int i=0;i<n;i++) {
 60         scanf("%d",a+i);
 61         b[i]=a[i];
 62     }
 63     int tot=n;
 64     for (int i=0;i<m;i++) {
 65         int x,y;
 66         scanf("%d %d",&x,&y);
 67         query[i].p=x-1;
 68         query[i].v=y;
 69         query[i].id=i;
 70         b[tot++]=y;
 71     }
 72     sort(b,b+tot);
 73     int k=unique(b,b+tot)-b;
 74     for (int i=0;i<n;i++) {
 75         a[i]=lower_bound(b,b+k,a[i])-b+1;
 76     }
 77     for (int i=0;i<m;i++) {
 78         query[i].v=lower_bound(b,b+k,query[i].v)-b+1;
 79     }
 80     int len=lis(n,f);
 81     for (int i=0;i<n;i++) {
 82         a[i]=N-a[i];
 83     }
 84     reverse(a,a+n);
 85     lis(n,g);
 86     reverse(g,g+n);
 87 
 88     reverse(a,a+n);
 89     for (int i=0;i<n;i++) {
 90         a[i]=N-a[i];
 91     }
 92 
 93     memset(cnt,0,sizeof cnt);
 94     for (int i=0;i<n;i++) {
 95         if (f[i]+g[i]-1==len) {
 96             cnt[f[i]]++;
 97         }
 98     }
 99     for (int i=0;i<n;i++) {
100         if (f[i]+g[i]-1==len&&cnt[f[i]]==1) {
101             flag[i]=true;
102         }
103     }
104 
105     sort(query,query+m);
106     for (int i=0;i<m;i++) {
107         int p=query[i].p;
108         if (flag[p])
109             query[i].ans=len-1;
110         else
111             query[i].ans=len;
112     }
113     int st=0;
114     memset(t,0,sizeof t);
115     for (int i=0;i<m;i++) {
116         int p=query[i].p;
117         for (;st<p;st++) {
118             int d=ask(a[st]-1);
119             upd(a[st],d+1);
120         }
121         int d=ask(query[i].v-1);
122         query[i].l=d;
123     }
124     memset(t,0,sizeof t);
125     for (int i=0;i<n;i++) {
126         a[i]=N-a[i];
127     }
128     st=n-1;
129     for (int i=m-1;i>=0;i--) {
130         int p=query[i].p;
131         query[i].v=N-query[i].v;
132         for (;st>p;st--) {
133             int d=ask(a[st]-1);
134             upd(a[st],d+1);
135         }
136         int d=ask(query[i].v-1);
137         query[i].r=d;
138         query[i].ans=max(query[i].ans,query[i].l+query[i].r+1);
139         ret[query[i].id]=query[i].ans;
140     }
141     for (int i=0;i<m;i++) {
142         printf("%d\n",ret[i]);
143     }
144     return 0;
145 }
View Code
  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <string>
  5 #include <string.h>
  6 #include <stdio.h>
  7 #include <math.h>
  8 #include <stdlib.h>
  9 #include <queue>
 10 #include <stack>
 11 #include <map>
 12 #include <set>
 13 
 14 using namespace std;
 15 
 16 const int N=1e6+12345;
 17 const int INF=0x3f3f3f3f;
 18 int a[N];
 19 struct Query {
 20     int p,v;
 21     int id;
 22     int ans;
 23     int l,r;
 24     bool operator < (const Query &o) const {
 25         return p<o.p;
 26     }
 27 }query[N];
 28 int dp[N];
 29 int f[N],g[N];
 30 int cnt[N];
 31 int lis(int n,int *f){
 32     fill(dp,dp+n,INF);
 33     for (int i=0;i<n;i++) {
 34         int pos=lower_bound(dp,dp+n,a[i])-dp;
 35         dp[pos]=a[i];
 36         f[i]=pos+1;
 37     }
 38     return lower_bound(dp,dp+n,INF)-dp;
 39 }
 40 bool flag[N];
 41 int ret[N];
 42 int main(){
 43     int n,m;
 44     scanf("%d %d",&n,&m);
 45     for (int i=0;i<n;i++) {
 46         scanf("%d",a+i);
 47     }
 48     for (int i=0;i<m;i++) {
 49         int x,y;
 50         scanf("%d %d",&x,&y);
 51         query[i].p=x-1;
 52         query[i].v=y;
 53         query[i].id=i;
 54     }
 55 
 56     int len=lis(n,f);
 57     for (int i=0;i<n;i++) {
 58         a[i]=-a[i];
 59     }
 60     reverse(a,a+n);
 61 
 62     lis(n,g);
 63     reverse(g,g+n);
 64 
 65 
 66     for (int i=0;i<n;i++) {
 67         a[i]=-a[i];
 68     }
 69     reverse(a,a+n);
 70 
 71     memset(cnt,0,sizeof cnt);
 72     for (int i=0;i<n;i++) {
 73         if (f[i]+g[i]-1==len) {
 74             cnt[f[i]]++;
 75         }
 76     }
 77     for (int i=0;i<n;i++) {
 78         if (f[i]+g[i]-1==len&&cnt[f[i]]==1) {
 79             flag[i]=true;
 80         }
 81     }
 82 
 83     sort(query,query+m);
 84     for (int i=0;i<m;i++) {
 85         int p=query[i].p;
 86         if (flag[p])
 87             query[i].ans=len-1;
 88         else
 89             query[i].ans=len;
 90     }
 91 
 92     int st=0;
 93     fill(dp,dp+n,INF);
 94     for (int i=0;i<m;i++) {
 95         int p=query[i].p;
 96         for (;st<p;st++) {
 97             int pos=lower_bound(dp,dp+n,a[st])-dp;
 98             dp[pos]=a[st];
 99         }
100         int pos=lower_bound(dp,dp+n,query[i].v)-dp;
101         query[i].l=pos;
102     }
103 
104 
105     for (int i=0;i<n;i++) {
106         a[i]=-a[i];
107     }
108     st=n-1;
109     fill(dp,dp+n,INF);
110     for (int i=m-1;i>=0;i--) {
111         int p=query[i].p;
112         for (;st>p;st--) {
113             int pos=lower_bound(dp,dp+n,a[st])-dp;
114             dp[pos]=a[st];
115         }
116         int pos=lower_bound(dp,dp+n,-query[i].v)-dp;
117         query[i].r=pos;
118         query[i].ans=max(query[i].ans,query[i].l+query[i].r+1);
119         ret[query[i].id]=query[i].ans;
120     }
121     for (int i=0;i<m;i++) {
122         printf("%d\n",ret[i]);
123     }
124     return 0;
125 }
View Code

 

posted @ 2016-03-08 19:19  活在夢裡  阅读(215)  评论(0编辑  收藏  举报