zoukankan      html  css  js  c++  java
  • 【BZOJ4553】【TJOI2016】【HEOI2016】序列

    cdq和整体二分之间的关系好迷啊

    原题:

     佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值

    可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你
    ,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可
    。注意:每种变化最多只有一个值发生变化。在样例输入1中,所有的变化是:
    1 2 3
    2 2 3
    1 3 3
    1 1 31 2 4
    选择子序列为原序列,即在任意一种变化中均为不降子序列在样例输入2中,所有的变化是:3 3 33 2 3选择子序列
    为第一个元素和第三个元素,或者第二个元素和第三个元素,均可满足要求
    n<=100,000
     
    这题在无上大神犇claris指点下发现是cdq分治,cdq分治这种东西我虽然会但是学的不好,遇到用cdq分治的题总能用(伪)整体二分做
    然后这道题似乎不能用整体二分了,至少我的整体二分错了,网上也找不到使用整体二分的题解
    所以只能看别人的代码搞cdq分治了,cdq分治的代码非常好懂,这道题很容易就看明白了,但是将思路扩展到更广泛的应用还需要继续思考
    所以先说一下此题的思路:
    首先先要明确一下题意,每次只能改一个数,如果想改另一个就必须先把这个数变回原来的再改另一个(这个我开始想的一段时间理解错了,看了题解才发现
    然后就可以用max[i]表示这个数最大能变成什么,min[i]是最小能变成什么
    酱紫就转化成一个近似lis(导弹拦截)的模型,能使f[j]转移到f[i]转移的条件是j<i,max[j]<=a[i],a[j]<=min[i],然后这就是个三维偏序的问题
    经典cdq分治
    先递归l到mid+1处理前半段,然后对前半段的a增序排序,后半段的min增序排序
    i从l到mid,在外面定义一个j=mid+1,每次如果min[j]<a[i],就更新j的答案并j++,在i的循环结束后还要j到r更新剩下的j的答案
    感觉好玄啊,其中的奥妙还需要更多的思考
    注意不能直接暴力memset树状数组,最好写个一清楚函数,比直接memset快不知道哪里去了
    代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 int rd(){int z=0,mk=1;  char ch=getchar();
     8     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
     9     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    10     return z*mk;
    11 }
    12 struct dcd{int x,y,z,id;}a[110000];
    13 int n,m,b[110000];
    14 int id[110000],mx[110000],mn[110000];
    15 int f[110000];
    16 dcd q[110000];
    17 int ans[110000];
    18 int e[110000],lbt[110000];
    19 void gtlbt(){  for(int i=1;i<=n;++i)  lbt[i]=i&-i;}
    20 //void mdf(int x,int y){  while(x<=n)  e[x]+=y,x+=lbt[x];}
    21 //int qr(int x){  int bwl=0;  while(x)  bwl+=e[x],x-=lbt[x];  return bwl;}
    22 void mdf(int x,int y){  while(x<=n)  e[x]=max(e[x],y),x+=lbt[x];}
    23 void dlt(int x){  while(x<=n)  e[x]=0,x+=lbt[x];}
    24 int qr(int x){  int bwl=0;  while(x)  bwl=max(bwl,e[x]),x-=lbt[x];  return bwl;}
    25 /*void bnr(int l,int r){
    26     if(l==r)  return ;
    27     int md=(l+r)>>1;
    28     *for(int i=l;i<=r;++i){
    29         if(a[i].y>=md)  ans[a[i].id]+=qr(a[i].x);
    30         if(a[i].x<=md)  mdf(a[i].z,1);
    31     }*
    32     //cout<<md<<endl;
    33     memset(e,0,sizeof(e));
    34     for(int i=l;i<=r;++i){
    35         //cout<<l<<" "<<r<<" "<<a[i].y<<" "<<a[i].x<<" "<<a[i].z<<endl;
    36         if(a[i].y>=md)  f[a[i].id]=max(f[a[i].id],qr(a[i].x)+1);
    37         if(a[i].x<=md)  mdf(a[i].z,f[a[i].id]);
    38     }
    39     //for(int i=l;i<=r;++i)if(a[i].x<=md)  mdf(a[i].z,-1);
    40     int t1=l,t2=md+1;
    41     for(int i=l;i<=r;++i)  q[(a[i].y<=md?t1:t2)++]=a[i];
    42     for(int i=l;i<=r;++i)  q[i]=q[i];
    43     bnr(l,md),bnr(md+1,r);
    44 }*/
    45 bool cmp1(dcd x,dcd y){  return x.x<y.x;}
    46 bool cmp2(dcd x,dcd y){  return x.y<y.y;}
    47 bool cmp3(dcd x,dcd y){  return x.id<y.id;}
    48 void cdq(int l,int r){
    49     if(l==r)  return ;
    50     int md=(l+r)>>1;
    51     cdq(l,md);
    52     sort(a+l,a+md+1,cmp1),sort(a+md+1,a+r+1,cmp2);
    53     //memset(e,0,sizeof(e));
    54     int j=md+1;
    55     for(int i=l;i<=md;++i){
    56         while(j<=r && a[j].y<a[i].x)  ans[a[j].id]=max(ans[a[j].id],qr(a[j].x)+1),++j;
    57         mdf(a[i].z,ans[a[i].id]);
    58     }
    59     while(j<=r)  ans[a[j].id]=max(ans[a[j].id],qr(a[j].x)+1),++j;
    60     for(int i=l;i<=md;++i)  dlt(a[i].z);
    61     sort(a+md+1,a+r+1,cmp3);
    62     cdq(md+1,r);
    63 }
    64 int main(){
    65     //freopen("ddd.in","r",stdin);
    66     //freopen("heoi2016_seq.in","r",stdin);
    67     //freopen("heoi2016_seq.out","w",stdout);
    68     memset(f,0,sizeof(f));
    69     cin>>n>>m;
    70     gtlbt();
    71     for(int i=1;i<=n;++i)  mx[i]=mn[i]=b[i]=rd();
    72     int l,r;
    73     while(m--){
    74         l=rd(),r=rd();
    75         mx[l]=max(mx[l],r),mn[l]=min(mn[l],r);
    76     }
    77     for(int i=1;i<=n;++i)  a[i].id=i,a[i].x=b[i],a[i].y=mn[i],a[i].z=mx[i],ans[i]=1;
    78     cdq(1,n);
    79     int mxx=0;
    80     for(int i=1;i<=n;++i)  mxx=max(mxx,ans[i]);
    81     cout<<mxx<<endl;
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    [ 9.10 ]CF每日一题系列—— 186A模拟处理字符串
    python查看删除你微信的账号
    python进阶之路4.2---装饰器
    python进阶之路4.1---生成器与迭代器
    Python进阶之路---1.4python数据类型-数字
    Python进阶之路---1.3python环境搭建
    Python进阶之路---1.2python版本差异
    Python进阶之路---1.1python简介
    麦进斗Magento2 SEO默认设置的完整策划
    如何修改Magento主题中的toplinks
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6476334.html
Copyright © 2011-2022 走看看