• 8.3题解


    T1[洛谷P3938]

    题目很明显了,菲波那契,找规律无疑了,考场上的话,如果你对菲波那契足够敏感,那我想你是可以想到正解的,毕竟考场14个人AC,还算挺水的,如果实在想不出来,可以暴力打表找一下父亲,毕竟你是要不停的翻父亲,不管用什么方法吧,最后会发现$fa[x]=x-fib(x的出生月份-1)$,那我们再考虑一下对于$le12$的数据,他不停的翻父亲最多会翻多少遍,你会发现也就60遍,这个时候这道题就可做了,甚至不需要倍增,完全可以直接翻,但是由于你不知道深度,所以需要先把两个点分别翻一遍,找到深度,然后用类似于倍增$lca$的方法直接翻就可以了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<set>
     4 #define maxf 62
     5 #define re register
     6 #define ll long long
     7 using namespace std;
     8 const int L=1<<20|1;
     9 char buffer[L],*S,*T;
    10 #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
    11 ll m;
    12 ll f[maxf];
    13 set <ll> ccc;
    14 inline ll read()
    15 {
    16     re ll aa=0,bb=1;re char cc=getchar();
    17     while(cc>'9'||cc<'0'){if(cc=='-') bb=-1;cc=getchar();}
    18     while(cc<='9'&&cc>='0'){aa=aa*10+cc-'0';cc=getchar();}
    19     return aa*bb;
    20 }
    21 inline int ef(re ll x)
    22 {
    23     re int l=1,r=61;
    24     while(l<r)
    25     {
    26         if(l+1==r)
    27         {
    28             if(x>f[l])  return r;
    29             else  return l;
    30         }
    31         re int mid=(l+r)>>1;
    32         if(x>f[mid])  l=mid+1;
    33         else  r=mid;
    34     }
    35     return l;
    36 }
    37 int main()
    38 {
    39     m=read();
    40     f[0]=1;  f[1]=1;
    41     for(re int i=2;i<maxf;++i)  f[i]=f[i-1]+f[i-2];
    42     for(re int i=1;i<=m;++i)
    43     {
    44         ll a=read(),b=read();  ll ls1=a,ls2=b;
    45         int deepa=0,deepb=0;
    46         while(ls1>1)  {deepa++;  ls1-=f[ef(ls1)-1];}
    47         while(ls2>1)  {deepb++;  ls2-=f[ef(ls2)-1];}
    48         if(deepa<deepb)  {swap(deepa,deepb);  swap(a,b);}
    49         while(deepa>deepb)  {a-=f[ef(a)-1]; deepa--;}
    50         while(a!=b)  {a-=f[ef(a)-1];  b-=f[ef(b)-1];}
    51         printf("%lld
    ",a);
    52     }
    53     return 0;
    54 }
    View Code

    T2[洛谷P3939]

    这题和BZOJ2120相似度不是一般的高啊,$BZOJ2120$可是个带修莫队的板子题,不过很可惜,我并没有学,后来颓了题解之后,给我一种这题很简单的感觉,只要$STL$可以6到飞起,这题就没问题,这题二元组排序,颜色做第一维,位置做第二维,先来考虑一下修改操作吧,你会发现他是交换$x$和$x+1$的位置,那对于你排好的序列是没有影响的,只要改掉位置就可以了,所以只需要lower_bound找到要修改的点,把第二维改一下就可以了,不过由于lower_ bound的特殊性,平常结构题进行二元组排序的思路被舍弃了,这时候有出现了一个新的$STL$:$pair$,其实就是个结构体,只不过已经定义好了,且只有两维,具体的实现方法可以参照下面的代码,修改搞定了,然后就是询问了,既然是按照颜色排序,那就只需要一个upper_bound和一个lower_bound,分别用来查找第一个大于$r$的位置和第一个大于等于$l$的位置,做差即可

    话说这题打$treap$,主席树,树套树等等,各种数据结构,大力卡常都可以拿到一个不错的成绩,$treap$都可以直接A

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define maxn 300100
     5 using namespace std;
     6 pair <int,int> a[maxn];
     7 int n,m;
     8 int Cc[maxn];
     9 inline int read(){
    10     register int ret;
    11     register char r;
    12     while(r=getchar(),r<'0'||r>'9');ret=r-48;
    13     while(r=getchar(),r>='0'&&r<='9')ret=ret*10+r-48;
    14     return ret;
    15 }
    16 int main()
    17 {
    18     n=read();  m=read();
    19     for(int i=1;i<=n;++i)  {a[i].first=read();  Cc[i]=a[i].first;  a[i].second=i;}
    20     sort(a+1,a+n+1);
    21     for(int i=1;i<=m;++i)
    22     {
    23         int opt=read();
    24         if(opt==1)
    25         {
    26             int l=read(),r=read(),Col=read();
    27             pair <int,int> ls;
    28             ls.first=Col;  ls.second=l;
    29             int wz1=lower_bound(a+1,a+n+1,ls)-a;
    30             pair <int,int> lss;
    31             lss.first=Col;  lss.second=r;
    32             int wz2=upper_bound(a+1,a+n+1,lss)-a;
    33             int ans=wz2-wz1;
    34             printf("%d
    ",ans);
    35         }
    36         else
    37         {
    38             int x=read();
    39             if(Cc[x]==Cc[x+1])  continue;
    40             else
    41             {
    42                 int ls=Cc[x];
    43                 pair <int,int> ls1;
    44                 ls1.first=Cc[x];  ls1.second=x;
    45                 int wz1=lower_bound(a+1,a+n+1,ls1)-a;
    46                 a[wz1].second=x+1;  Cc[x]=Cc[x+1];
    47                 pair <int,int> ls2;
    48                 ls2.first=Cc[x+1];  ls2.second=x+1;
    49                 int wz2=lower_bound(a+1,a+n+1,ls2)-a;
    50                 a[wz2].second=x;  Cc[x+1]=ls;
    51             }
    52         }
    53     }
    54     return 0;
    55 }
    View Code

    T3[洛谷P3940]

    这题$k==1||k==2$一看就友好啊,先骗8分没问题

    说实话$k==1$就是个暴力,因为每个块内都不能冲突,所以暴力扫一遍,碰到冲突的直接分组就可以了,字典序最小的话就是前面多分组,后面少分组呗,那从后向前扫,直接贪心就可做,不过如果暴力扫当前块中的数,判是否冲突的话,很大的可能性会T,我们会发现他有一个有趣的性质,最大的数为什么是131072呢,一般不都应该是$le$几之类的数嘛,好巧不巧,两个131072加和,恰好是$512^2$,那我们枚举512,肯定比枚举当前块所有的数划算啊,所以,直接枚举到512,列出所有的平方数,和当前准备加入的点做差,看看这个差是否存在在当前组内就可以了

    对于$k==2$,和关押罪犯有些像,而这两道题,用并查集或交叉染色判二分图都可做,我用的二分图,每加入一个点,就对当前组内所有的点跑一遍二分图,如果不能构成二分图,直接分组即可,并查集的思想和这个类似,依旧是从后往前扫贪心

    $tips$:清空的时候不要$memset$,放进去几个点清空几个点,不然一不注意就会T,不过一定要清空啊!!还有就是重复的点,建图的时候别忘了

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<vector>
      5 #include<cstring>
      6 #define maxn 270000
      7 using namespace std;
      8 /*const int L=1<<20|1;
      9 char buffer[L],*S,*T;
     10 #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)*/
     11 int n,k,js=1;
     12 int a[maxn],ans[maxn],pd[maxn];
     13 vector <int> b[maxn],bb[maxn],c[maxn];
     14 int jss,bjjj;
     15 int head[maxn],to[maxn*2],xia[maxn*2],visit[maxn];
     16 inline int read()
     17 {
     18     int ret;
     19     char r;
     20     while(r=getchar(),r<'0'||r>'9');ret=r-48;
     21     while(r=getchar(),r>='0'&&r<='9')ret=ret*10+r-48;
     22     return ret;
     23 }
     24 void add(int x,int y)
     25 {
     26     to[++jss]=y;  xia[jss]=head[x];  head[x]=jss;
     27 }
     28 void dfs(int x,int colo)
     29 {
     30     visit[x]=colo;
     31     for(int i=head[x];i;i=xia[i])
     32     {
     33         int ls=to[i];
     34         if(ls<=bb[js][0])
     35         {
     36             if(visit[ls]==0)  dfs(ls,3-colo);
     37             else if(visit[ls]==colo)  {bjjj=1;  return ;}
     38         }
     39     }
     40 }
     41 int main()
     42 {
     43 //    freopen("division18.in","r",stdin);
     44     n=read();  k=read();
     45     for(int i=1;i<=n;++i)  a[i]=read();
     46     if(k==1)
     47     {
     48         int zz=n;
     49         while(zz>0)
     50         {
     51             if(b[js].size()!=0)
     52                 for(int i=2;i<=512;++i)
     53                 {
     54                     int ls1=i*i-a[zz];
     55                     if(pd[ls1]==1)
     56                     {
     57                         for(int i=0;i<b[js].size();++i)  pd[b[js][i]]=0;
     58                         ans[++js]=zz;  break;
     59                     }
     60                 }
     61             b[js].push_back(a[zz]);  pd[a[zz]]=1;  zz--;
     62         }
     63         printf("%d
    ",js);
     64         for(int i=js;i>=2;--i)  printf("%d ",ans[i]);
     65         puts("");
     66     }
     67     else
     68     {
     69         for(int i=n;i>=1;--i)
     70         {
     71             if(b[js].size()==0)
     72             {
     73                 b[js].push_back(a[i]);  bb[js].push_back(i);
     74                 pd[a[i]]=1;  c[a[i]].push_back(i);
     75                 continue;
     76             }
     77             for(int j=2;j<=512;++j)
     78             {
     79                 int ls1=j*j-a[i];  bjjj=0;
     80                 if(pd[ls1]!=0)
     81                 {
     82                     for(int k=0;k<c[ls1].size();++k)
     83                         if(js==1||c[ls1][k]<=bb[js][0])
     84                             {add(c[ls1][k],i);  add(i,c[ls1][k]);}
     85                     for(int k=0;k<bb[js].size();++k)  visit[bb[js][k]]=0;
     86                     for(int k=0;k<bb[js].size();++k)
     87                         if(visit[bb[js][k]]==0)  dfs(bb[js][k],1);
     88                     for(int k=0;k<bb[js].size();++k)  visit[bb[js][k]]=0;
     89                     visit[i]=0;
     90                 }
     91                 if(bjjj==1)
     92                 {
     93                     for(int k=1;k<=jss;++k)  {to[k]=0;  xia[k]=0;}
     94                     for(int k=0;k<b[js].size();++k)
     95                                             {head[bb[js][k]]=0;  pd[b[js][k]]=0;}
     96                     head[i]=0;  jss=0;  js++;
     97                 }
     98             }
     99             b[js].push_back(a[i]);  bb[js].push_back(i);
    100             c[a[i]].push_back(i);  pd[a[i]]=1;
    101         }
    102         printf("%d
    ",js);
    103         for(int i=js;i>=2;--i)  printf("%d ",bb[i][0]);
    104         puts("");
    105     }
    106     return 0;
    107 }
    View Code
  • 相关阅读:
    HDU 6214 Smallest Minimum Cut 最小割,权值编码
    HDU 6196 happy happy happy 爆搜加剪枝
    2017 ACM-ICPC 亚洲区(西安赛区)网络赛 Coin 概率+矩阵快速幂
    HDU 6199 2017沈阳网络赛 DP
    HDU 6200 2017沈阳网络赛 树上区间更新,求和
    HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组
    docker平时使用异常记录
    AI模型运维——NVIDIA驱动、cuda、cudnn、nccl安装
    python——平时遇到问题记录
    python——虚拟环境管理大合集
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11299372.html
Copyright © 2020-2023  润新知