• 7.25题解


    两道水题,都贼惨,难受。。。。。。。一大把伤心往事以及蒟蒻的自己,今天上午的我,绝对像个zz

    T1

    emm,KMP,hash任您挑选,当然我忘了KMP怎么玩,就去打了hash,就这想式子还想了半天,不过点和长度之间的转换最后还是被我玩死了,没倒腾对,不过我最后还是hash过的,hash的话就O(n)长度扫一遍就行了,完全可以作为hash模板题,还是我废物啊,别的就没啥可说的了,注意一下小的细节就可以了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 using namespace std;
     6 #define maxn 200010
     7 #define ll long long
     8 #define ull unsigned long long
     9 int t;
    10 const ll p=131;
    11 char s[maxn],c[2];
    12 int la,lb;
    13 ull zhia[maxn],zhib[maxn],jc[maxn];
    14 int check(int cd)
    15 {
    16     if(!cd) return 1;
    17     if(zhia[cd]==(zhib[lb]-zhib[lb-cd]*jc[cd])) return 1;
    18     return 0;
    19 }
    20 int ef(int head,int tail)
    21 {
    22     if(head==tail) return head;
    23     if(head+1==tail) return check(tail)?tail:head;
    24     int mid=(head+tail)/2;
    25     if(check(mid))return ef(mid,tail);
    26     else return ef(head,mid-1);
    27 }
    28 int main()
    29 {
    30     scanf("%d",&t);
    31     jc[0]=1; jc[1]=p;
    32     for(int i=2;i<maxn;++i) jc[i]=jc[i-1]*p;
    33     while(t--)
    34     {
    35         memset(zhia,0,sizeof(zhia));
    36         memset(zhib,0,sizeof(zhib));
    37         scanf("%d%d",&la,&lb);
    38         scanf("%s",s);
    39         int ls;
    40         for(int i=1;i<=la;++i)
    41         {
    42             ls=s[i-1]-'a'+1;
    43             zhia[i]=zhia[i-1]*p+ls;
    44             if(i<=lb) zhib[i]=zhib[i-1]*p+ls;
    45         }
    46         scanf("%s",c); 
    47         lb++;
    48         ls=c[0]-'a'+1;
    49         zhib[lb]=zhib[lb-1]*p+ls;
    50         int ans=0;
    51         for(int i=1;i<=min(la,lb);++i)
    52             if(zhia[i]==(zhib[lb]-zhib[lb-i]*jc[i])) ans=i;
    53         cout<<ans<<endl;
    54     }
    55     return 0;
    56 }
    暴力出奇迹

    T2

    好好读题,多画样例,仔细思考,别跟我似的,想着啥是啥,打完就扔,我是废物,太废物了,这道题,乍一看给你一种打板子求割点就是正解的错觉,事实上坑还是在的,就是从1到n的必经点肯定是割点,但不见得割点就是必经点,因为有可能从1到n某些割点根本就不需要经过,所以这题你给他点双缩点,然后dfs从1跑到n,标记一下途中经过的割点,那些割点就是最终答案了,记得数组稍微开大一点,记请缩点前后的对应关系就没问题了

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<vector>
      4 #include<stack>
      5 #include<cstring>
      6 #define maxn 200100
      7 #define maxm 400100
      8 using namespace std;
      9 int T,n,m,js,root,tot,cnt,num,j,ans;
     10 int head[maxn],to[maxm*2],xia[maxm*2];
     11 int dfn[maxn],low[maxn],cut[maxn];
     12 int bh[maxn],ss[maxn];
     13 int h[maxn*2],t[maxm*2],x[maxm*2];
     14 int pd[maxn*2],ys[maxn*2];
     15 vector <int> ds[maxn*2];
     16 stack <int> s;
     17 void clear()
     18 {
     19     js=0;  root=0;  tot=0;  num=0;  j=0;  ans=0;
     20     while(s.empty()==false)  s.pop();
     21     for(int i=1;i<=cnt;++i)  ds[i].clear();
     22     memset(head,0,sizeof(head));  memset(to,0,sizeof(to));
     23     memset(xia,0,sizeof(xia));  memset(dfn,0,sizeof(dfn));
     24     memset(low,0,sizeof(low));  memset(cut,0,sizeof(cut));
     25     memset(bh,0,sizeof(bh));  memset(ss,0,sizeof(ss));
     26     memset(h,0,sizeof(h));  memset(t,0,sizeof(t));  memset(x,0,sizeof(x));
     27     memset(pd,0,sizeof(pd));  memset(ys,0,sizeof(ys));
     28     cnt=0;
     29 }
     30 void add(int x,int y)
     31 {
     32     to[++js]=y;  xia[js]=head[x];  head[x]=js;
     33 }
     34 void tarjan(int x)
     35 {
     36     int bj=0;  dfn[x]=low[x]=++tot;  s.push(x);
     37     if(x==root&&head[x]==0)  {ds[++cnt].push_back(x);  return ;}
     38     for(int i=head[x];i;i=xia[i])
     39     {
     40         int ls=to[i];
     41         if(dfn[ls]==0)
     42         {
     43             tarjan(ls);  low[x]=min(low[x],low[ls]);
     44             if(low[ls]>=dfn[x])
     45             {
     46                 bj++;
     47                 if(x!=root||bj>=2)  cut[x]=1;
     48                 int y;  cnt++;
     49                 do  {y=s.top();  s.pop();  ds[cnt].push_back(y);}
     50                 while(y!=ls);
     51                 ds[cnt].push_back(x);
     52             }
     53         }
     54         else  low[x]=min(low[x],dfn[ls]);
     55     }
     56 }
     57 void ADD(int a,int b)
     58 {
     59     t[++j]=b;  x[j]=h[a];  h[a]=j;
     60 }
     61 void dfs(int w)
     62 {
     63     ys[w]=1;
     64     if(pd[w]==1)  return ;
     65     for(int i=h[w];i;i=x[i])
     66     {
     67         int ls=t[i];
     68         if(ys[ls]==0)
     69         {    
     70             dfs(ls);
     71             if(pd[ls]==1)  pd[w]=1;
     72         }
     73     }
     74 }
     75 int main()
     76 {
     77     scanf("%d",&T);
     78     while(T--)
     79     {
     80         scanf("%d%d",&n,&m);
     81         for(int i=1;i<=m;++i)
     82         {
     83             int u,v;  scanf("%d%d",&u,&v);
     84             add(u,v);  add(v,u);
     85         }
     86         for(int i=1;i<=n;++i)
     87             if(dfn[i]==0)  {root=i;  tarjan(i);}
     88         num=cnt;
     89         for(int i=1;i<=n;++i)
     90             if(cut[i]==1)  bh[i]=++num;
     91         for(int i=1;i<=cnt;++i)
     92             for(int j=0;j<ds[i].size();++j)
     93             {
     94                 int ls=ds[i][j];
     95                 if(cut[ls]==1)  {ADD(i,bh[ls]);  ADD(bh[ls],i);}
     96                 else  ss[ls]=i;
     97             }
     98         if(cut[n]==1)  pd[bh[n]]=1;
     99         else  pd[ss[n]]=1;
    100         if(cut[1]==1)  dfs(bh[1]);
    101         else  dfs(ss[1]);
    102         for(int i=2;i<n;++i)
    103         {
    104             int ls;
    105             if(cut[i]==1)  ls=bh[i];
    106             else  ls=ss[i];  
    107             if(pd[ls]==1&&cut[i]==1)  ans++;
    108         }
    109         printf("%d
    ",ans);
    110         for(int i=2;i<n;++i)
    111         {
    112             int ls;
    113             if(cut[i]==1)  ls=bh[i];
    114             else  ls=ss[i];  
    115             if(pd[ls]==1&&cut[i]==1)  printf("%d ",i);
    116         }
    117         puts("");  clear();
    118     }
    119     return 0;
    120 }
    模板出奇迹

    T3

    唯一一道不水的题,让我改了两天,什么破情况,昨天晚上真的改到自闭,回到正题

    一个环,要求把颜色一样的挪到一起,这种题一般第一步都是,拆环为链变二倍,然后怎么办呢?枚举每个断点,看这么断的最少移动次数,这就O(n)起步了,再加个n什么之类的估计就死翘翘了,这题我没打部分分,就直接上正解了,(sdfz那大佬三分搞到65分,可惜我不会)

    我们把$BR$的排列具化成01串,谁0谁1无所谓,我们假设把0留在中间,那么1被挪到两边需要的移动次数应该就是他移动的方向上0的个数,那么我们来想一下怎么移动最优?也就是怎么样能让每个1两边的0最少,当然是以中间的0为不动点咯,那这样的话我们记录一下每个1两边0的个数就可以了,正着倒着扫一下就好了,我们来想一下这一个序列中所有的1一共要移动的次数,$∑(qian[j]-qian[i-1])+∑(hou[j]-hou[i+len])$,来理解一下这个式子,$qian$就是刚才记录的那个前面有几个0,$hou$记录后面有几个(倒着记录),j代表为1的点,$qian[j]$中的$j$为在中间0前面的点,$hou[j]$中的$j$为在中间0后面的点,$i$代表枚举开始的点,$i+len-1$是枚举结束的点,那这个式子就是用前缀和后缀算出中间一部分,现在我们把它拆开就变成了$∑qian[j]-∑qian[i-1]+∑hou[j]-∑[i+len]$,仔细一看,这个$qian[j]$,$hou[j]$的有点前缀和的意思啊,$yes$,就是前缀和,不对,准确来说是前缀和的前缀和以及后缀和的前缀和,那式子都有了,码就完了,虽然我码了很久。。附赠一下我最后推出来的完整的式子

    $ans=qh[mid]-qh[i-1]-qian[i-1]*len1+hh[mid+1]-hh[i+len]-hou[mid+1]*len2$

    $len1=(mid-i+1)-(qian[mid]-qian[i-1])$

    $len2=(i+len-1-(mid+1)+1)-(hou[mid]-hou[i+len])$

    我打的应该不太算正解,因为我拿到的正解需要二分,我实在不觉得决策具有单调性,所以放弃了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define maxn 1001000
     5 #define int long long
     6 using namespace std;
     7 int t,len,tot,ans;
     8 int cun[maxn*2],qian[maxn*2],hou[maxn*2],qh[maxn*2],hh[maxn*2],jl[maxn*2];
     9 char a[maxn];
    10 void clear()
    11 {
    12     tot=0;  ans=200000000000000000;
    13     memset(cun,0,sizeof(cun));  memset(qian,0,sizeof(qian));
    14     memset(hou,0,sizeof(hou));  memset(qh,0,sizeof(qh));
    15     memset(hh,0,sizeof(hh));  memset(jl,0,sizeof(jl));
    16 }
    17 signed main()
    18 {
    19     scanf("%lld",&t);
    20     while(t--)
    21     {
    22         clear();
    23         scanf("%s",a+1);  len=strlen(a+1);
    24         for(int i=1;i<=len;++i)
    25         {
    26             if(a[i]=='B')  cun[i]=1;
    27             else  {cun[i]=0;  tot++;}
    28         }
    29         for(int i=len+1;i<=2*len;++i)  cun[i]=cun[i-len];
    30         int cnt=0;  tot*=2;
    31         for(int i=1;i<=2*len;++i)
    32         {
    33             if(cun[i]==0)  {cnt++;  jl[cnt]=i;  qian[i]=cnt;  hou[i]=tot-qian[i]+1;}
    34             if(cun[i]==1)  {qian[i]=cnt;  hou[i]=tot-qian[i];}
    35             if(cun[i]==0)  qh[i]=qh[i-1];
    36             else  qh[i]=qh[i-1]+qian[i];
    37         }
    38         for(int i=2*len;i>=1;--i)
    39         {
    40             if(cun[i]==0)  hh[i]=hh[i+1];
    41             else  hh[i]=hh[i+1]+hou[i];
    42         }
    43         for(int i=1;i<=len;++i)
    44         {
    45             int da=0;
    46             int mid=(qian[i+len-1]-qian[i-1])/2+1+qian[i-1];  mid=jl[mid];
    47             da=qh[mid]-qh[i-1]-qian[i-1]*(mid-i+1-qian[mid]+qian[i-1]);
    48             da+=hh[mid+1]-hh[i+len]-hou[i+len]*(i+len-mid-1-hou[mid+1]+hou[i+len]);
    49             ans=min(ans,da);
    50         }
    51         printf("%lld
    ",ans);
    52     }
    53     return 0;
    54 }
    模拟?
  • 相关阅读:
    堆排序回顾
    动画函数封装
    mouseenter 和mouseover的区别
    元素滚动 scroll 系列
    元素可视区 client 系列
    元素偏移量 offset 系列
    JS执行机制
    BOM
    常用键盘事件
    常用鼠标事件
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11256749.html
Copyright © 2020-2023  润新知