• 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
    ",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
    ",ret[i]);
    123     }
    124     return 0;
    125 }
    View Code
  • 相关阅读:
    C# 杨辉三角 下
    C# 自动走迷宫 下
    算法练习之1数字填充 下
    动态添加控件并获取其值
    两个ListBox的互动
    VS2005常用快捷键
    GridView内嵌DropDownList操作
    GridView格式化短日期
    获得客户端ID
    Access数据库 Update 语句的怪现象
  • 原文地址:https://www.cnblogs.com/micrari/p/5255264.html
Copyright © 2020-2023  润新知