• 8.1题解


    下午有点不舒服,这个人状态都不好了,一道破题,两个zz错误搞了一下午,刚刚水了道题,几年前的NOIP真水

    T1

    怎么说呢,暴力40,跟排序那道题有点像,线段树维护01串,二分答案,不过这道题,某Larry实测,n遍二分,T到飞,正解嘛。着实和那道题有点像,那道题是线段树维护1的个数,也就是区间和,排序通过区间覆盖实现,这道题的话,线段树维护每个区间中26个字母出现的次数,dalao讲题的时候说用桶,我无比懵逼,结果不就是数组维护字母出现的个数嘛,说的倒挺高大上,可能还是我太弱了叭,然后进行覆盖,之后输出的时候搜到底输出即可,不过出题人卡常真心恶心,正解T90?for循环展开就A了,实属稍恶心

      1 #include<iostream>
      2 #include<cstdio>
      3 #define maxn 100100
      4 #define maxx 28
      5 using namespace std;
      6 struct node{
      7     int zuo,you;
      8     int tong[maxx],lan;
      9 }s[maxn*4],cun;
     10 int n,m;
     11 int a[maxn];
     12 char aa[maxn];
     13 inline void mem(int f)
     14 {
     15     for(int i=1;i<=26;++i)  s[f].tong[i]=0;
     16 }
     17 inline void up(int f)
     18 {
     19     for(int i=1;i<=26;++i)  s[f].tong[i]=s[2*f].tong[i]+s[2*f+1].tong[i];
     20 }
     21 inline void down(int f)
     22 {
     23     if(s[f].zuo==s[f].you)  return ;
     24     if(s[f].lan)
     25     {
     26         int ls=s[f].lan;
     27         mem(2*f);  mem(2*f+1);
     28         s[2*f].tong[ls]=s[2*f].you-s[2*f].zuo+1;
     29         s[2*f+1].tong[ls]=s[2*f+1].you-s[2*f+1].zuo+1;
     30         s[2*f].lan=ls;  s[2*f+1].lan=ls;  s[f].lan=0;
     31     }
     32 }
     33 inline void build(int f,int l,int r)
     34 {
     35     s[f].zuo=l;  s[f].you=r;
     36     if(l==r)  {s[f].tong[a[l]]++;  return ;}
     37     int mid=(s[f].zuo+s[f].you)>>1;
     38     build(2*f,l,mid);  build(2*f+1,mid+1,r);
     39     up(f);
     40 }
     41 inline void quary(int f,int l,int r)
     42 {
     43     if(s[f].zuo>=l&&s[f].you<=r)
     44     {
     45         for(int i=1;i<=26;++i)  cun.tong[i]+=s[f].tong[i];
     46         return ;
     47     }
     48     down(f);
     49     int mid=(s[f].zuo+s[f].you)>>1;
     50     if(l<=mid)  quary(2*f,l,r);
     51     if(r>mid)  quary(2*f+1,l,r);
     52 }
     53 inline void change(int f,int l,int r,int w)
     54 {
     55     if(s[f].zuo>=l&&s[f].you<=r)
     56     {
     57         mem(f);  s[f].tong[w]=s[f].you-s[f].zuo+1;
     58         s[f].lan=w;  return ;
     59     }
     60     down(f);
     61     int mid=(s[f].zuo+s[f].you)>>1;
     62     if(l<=mid)  change(2*f,l,r,w);
     63     if(r>mid)  change(2*f+1,l,r,w);
     64     up(f);
     65 }
     66 inline void out(int f)
     67 {
     68     char ans;
     69     if(s[f].zuo==s[f].you)
     70     {
     71         for(int i=1;i<=26;++i)
     72             if(s[f].tong[i])  ans=i-1+'a';
     73         printf("%c",ans);
     74         return ;
     75     }
     76     down(f);  out(2*f);  out(2*f+1);
     77 }
     78 int main()
     79 {
     80     scanf("%d%d",&n,&m);  scanf("%s",aa+1);
     81     for(int i=1;i<=n;++i)  a[i]=aa[i]-'a'+1;
     82     build(1,1,n);
     83     for(int i=1;i<=m;++i)
     84     {
     85         int l,r,x;  scanf("%d%d%d",&l,&r,&x);
     86         for(int i=1;i<=26;++i)  cun.tong[i]=0;
     87         quary(1,l,r);
     88         if(x==0)
     89         {
     90             int js=l;
     91             for(int i=26;i>=1;--i)
     92                 if(cun.tong[i])  {change(1,js,js+cun.tong[i]-1,i);  js+=cun.tong[i];}
     93         }
     94         else
     95         {
     96             int js=l;
     97             for(int i=1;i<=26;++i)
     98                 if(cun.tong[i])  {change(1,js,js+cun.tong[i]-1,i);  js+=cun.tong[i];}
     99         }
    100     }
    101     out(1);  puts("");
    102     return 0;
    103 }
    T90
      1 #include<iostream>
      2 #include<cstdio>
      3 #define maxn 100100
      4 #define maxx 28
      5 using namespace std;
      6 struct node{
      7     int zuo,you;
      8     int tong[maxx],lan;
      9 }s[maxn*4],cun;
     10 int n,m;
     11 int a[maxn];
     12 char aa[maxn];
     13 inline void mem(int f)
     14 {
     15     s[f].tong[1]=0;  s[f].tong[2]=0;  s[f].tong[3]=0;
     16     s[f].tong[4]=0;  s[f].tong[5]=0;  s[f].tong[6]=0;
     17     s[f].tong[7]=0;  s[f].tong[8]=0;  s[f].tong[9]=0;
     18     s[f].tong[10]=0;  s[f].tong[11]=0;  s[f].tong[12]=0;
     19     s[f].tong[13]=0;  s[f].tong[14]=0;  s[f].tong[15]=0;
     20     s[f].tong[16]=0;  s[f].tong[17]=0;  s[f].tong[18]=0;
     21     s[f].tong[19]=0;  s[f].tong[20]=0;  s[f].tong[21]=0;
     22     s[f].tong[22]=0;  s[f].tong[23]=0;  s[f].tong[24]=0;
     23     s[f].tong[25]=0;  s[f].tong[26]=0;
     24 }
     25 inline void up(int f)
     26 {
     27     s[f].tong[1]=s[2*f].tong[1]+s[2*f+1].tong[1];
     28     s[f].tong[2]=s[2*f].tong[2]+s[2*f+1].tong[2];
     29     s[f].tong[3]=s[2*f].tong[3]+s[2*f+1].tong[3];
     30     s[f].tong[4]=s[2*f].tong[4]+s[2*f+1].tong[4];
     31     s[f].tong[5]=s[2*f].tong[5]+s[2*f+1].tong[5];
     32     s[f].tong[6]=s[2*f].tong[6]+s[2*f+1].tong[6];
     33     s[f].tong[7]=s[2*f].tong[7]+s[2*f+1].tong[7];
     34     s[f].tong[8]=s[2*f].tong[8]+s[2*f+1].tong[8];
     35     s[f].tong[9]=s[2*f].tong[9]+s[2*f+1].tong[9];
     36     s[f].tong[10]=s[2*f].tong[10]+s[2*f+1].tong[10];
     37     s[f].tong[11]=s[2*f].tong[11]+s[2*f+1].tong[11];
     38     s[f].tong[12]=s[2*f].tong[12]+s[2*f+1].tong[12];
     39     s[f].tong[13]=s[2*f].tong[13]+s[2*f+1].tong[13];
     40     s[f].tong[14]=s[2*f].tong[14]+s[2*f+1].tong[14];
     41     s[f].tong[15]=s[2*f].tong[15]+s[2*f+1].tong[15];
     42     s[f].tong[16]=s[2*f].tong[16]+s[2*f+1].tong[16];
     43     s[f].tong[17]=s[2*f].tong[17]+s[2*f+1].tong[17];
     44     s[f].tong[18]=s[2*f].tong[18]+s[2*f+1].tong[18];
     45     s[f].tong[19]=s[2*f].tong[19]+s[2*f+1].tong[19];
     46     s[f].tong[20]=s[2*f].tong[20]+s[2*f+1].tong[20];
     47     s[f].tong[21]=s[2*f].tong[21]+s[2*f+1].tong[21];
     48     s[f].tong[22]=s[2*f].tong[22]+s[2*f+1].tong[22];
     49     s[f].tong[23]=s[2*f].tong[23]+s[2*f+1].tong[23];
     50     s[f].tong[24]=s[2*f].tong[24]+s[2*f+1].tong[24];
     51     s[f].tong[25]=s[2*f].tong[25]+s[2*f+1].tong[25];
     52     s[f].tong[26]=s[2*f].tong[26]+s[2*f+1].tong[26];
     53 }
     54 inline void down(int f)
     55 {
     56     if(s[f].zuo==s[f].you)  return ;
     57     if(s[f].lan)
     58     {
     59         int ls=s[f].lan;
     60         mem(2*f);  mem(2*f+1);
     61         s[2*f].tong[ls]=s[2*f].you-s[2*f].zuo+1;
     62         s[2*f+1].tong[ls]=s[2*f+1].you-s[2*f+1].zuo+1;
     63         s[2*f].lan=ls;  s[2*f+1].lan=ls;  s[f].lan=0;
     64     }
     65 }
     66 inline void build(int f,int l,int r)
     67 {
     68     s[f].zuo=l;  s[f].you=r;
     69     if(l==r)  {s[f].tong[a[l]]++;  return ;}
     70     int mid=(s[f].zuo+s[f].you)>>1;
     71     build(2*f,l,mid);  build(2*f+1,mid+1,r);
     72     up(f);
     73 }
     74 inline void quary(int f,int l,int r)
     75 {
     76     if(s[f].zuo>=l&&s[f].you<=r)
     77     {
     78         cun.tong[1]+=s[f].tong[1];
     79         cun.tong[2]+=s[f].tong[2];
     80         cun.tong[3]+=s[f].tong[3];
     81         cun.tong[4]+=s[f].tong[4];
     82         cun.tong[5]+=s[f].tong[5];
     83         cun.tong[6]+=s[f].tong[6];
     84         cun.tong[7]+=s[f].tong[7];
     85         cun.tong[8]+=s[f].tong[8];
     86         cun.tong[9]+=s[f].tong[9];
     87         cun.tong[10]+=s[f].tong[10];
     88         cun.tong[11]+=s[f].tong[11];
     89         cun.tong[12]+=s[f].tong[12];
     90         cun.tong[13]+=s[f].tong[13];
     91         cun.tong[14]+=s[f].tong[14];
     92         cun.tong[15]+=s[f].tong[15];
     93         cun.tong[16]+=s[f].tong[16];
     94         cun.tong[17]+=s[f].tong[17];
     95         cun.tong[18]+=s[f].tong[18];
     96         cun.tong[19]+=s[f].tong[19];
     97         cun.tong[20]+=s[f].tong[20];
     98         cun.tong[21]+=s[f].tong[21];
     99         cun.tong[22]+=s[f].tong[22];
    100         cun.tong[23]+=s[f].tong[23];
    101         cun.tong[24]+=s[f].tong[24];
    102         cun.tong[25]+=s[f].tong[25];
    103         cun.tong[26]+=s[f].tong[26];
    104         return ;
    105     }
    106     down(f);
    107     int mid=(s[f].zuo+s[f].you)>>1;
    108     if(l<=mid)  quary(2*f,l,r);
    109     if(r>mid)  quary(2*f+1,l,r);
    110 }
    111 inline void change(int f,int l,int r,int w)
    112 {
    113     if(s[f].zuo>=l&&s[f].you<=r)
    114     {
    115         mem(f);  s[f].tong[w]=s[f].you-s[f].zuo+1;
    116         s[f].lan=w;  return ;
    117     }
    118     down(f);
    119     int mid=(s[f].zuo+s[f].you)>>1;
    120     if(l<=mid)  change(2*f,l,r,w);
    121     if(r>mid)  change(2*f+1,l,r,w);
    122     up(f);
    123 }
    124 inline void out(int f)
    125 {
    126     char ans;
    127     if(s[f].zuo==s[f].you)
    128     {
    129         if(s[f].tong[1])  ans=1-1+'a';
    130         if(s[f].tong[2])  ans=2-1+'a';
    131         if(s[f].tong[3])  ans=3-1+'a';
    132         if(s[f].tong[4])  ans=4-1+'a';
    133         if(s[f].tong[5])  ans=5-1+'a';
    134         if(s[f].tong[6])  ans=6-1+'a';
    135         if(s[f].tong[7])  ans=7-1+'a';
    136         if(s[f].tong[8])  ans=8-1+'a';
    137         if(s[f].tong[9])  ans=9-1+'a';
    138         if(s[f].tong[10])  ans=10-1+'a';
    139         if(s[f].tong[11])  ans=11-1+'a';
    140         if(s[f].tong[12])  ans=12-1+'a';
    141         if(s[f].tong[13])  ans=13-1+'a';
    142         if(s[f].tong[14])  ans=14-1+'a';
    143         if(s[f].tong[15])  ans=15-1+'a';
    144         if(s[f].tong[16])  ans=16-1+'a';
    145         if(s[f].tong[17])  ans=17-1+'a';
    146         if(s[f].tong[18])  ans=18-1+'a';
    147         if(s[f].tong[19])  ans=19-1+'a';
    148         if(s[f].tong[20])  ans=20-1+'a';
    149         if(s[f].tong[21])  ans=21-1+'a';
    150         if(s[f].tong[22])  ans=22-1+'a';
    151         if(s[f].tong[23])  ans=23-1+'a';
    152         if(s[f].tong[24])  ans=24-1+'a';
    153         if(s[f].tong[25])  ans=25-1+'a';
    154         if(s[f].tong[26])  ans=26-1+'a';
    155         printf("%c",ans);
    156         return ;
    157     }
    158     down(f);  out(2*f);  out(2*f+1);
    159 }
    160 int main()
    161 {
    162     scanf("%d%d",&n,&m);  scanf("%s",aa+1);
    163     for(int i=1;i<=n;++i)  a[i]=aa[i]-'a'+1;
    164     build(1,1,n);
    165     for(int i=1;i<=m;++i)
    166     {
    167         int l,r,x;  scanf("%d%d%d",&l,&r,&x);
    168         for(int i=1;i<=26;++i)  cun.tong[i]=0;
    169         quary(1,l,r);
    170         if(x==0)
    171         {
    172             int js=l;
    173             for(int i=26;i>=1;--i)
    174                 if(cun.tong[i])  {change(1,js,js+cun.tong[i]-1,i);  js+=cun.tong[i];}
    175         }
    176         else
    177         {
    178             int js=l;
    179             for(int i=1;i<=26;++i)
    180                 if(cun.tong[i])  {change(1,js,js+cun.tong[i]-1,i);  js+=cun.tong[i];}
    181         }
    182     }
    183     out(1);  puts("");
    184     return 0;
    185 }
    前方AC代码,请做好心理准备

    那个懒标记我一开始记麻烦了,就不误导大家了,不过在线段树中懒标记确实很重要,做题的时候最好仔细思考一下懒标记为什么这么记,以及这么记带来的效果和便利是什么

    T2

    一道脑回路清奇的dp题,是道拓宽思路的好题,光dp定义,我就理解了很久,wjn考场AC,属实nb,上题解

    设$dp[i][j]$代表当前处理到第$i$列,有$j$个右区间的左端点在第$i$列及其以左,放置了1,也就是放了$j$个1,不过是右区间中的$j$个,要不换个说法?有$j$个右区间在第$i$列及其以左放了1,emm大概是这样了,这样的话dp转移就由传统的按行或按格转移,变为了按列转移,状态转移的话我们先考虑那个乱入的右区间

    $do[i][j]+=dp[i-1][j]$

    这个就是不放一,很好理解

    $do[i][j]+=dp[i-1][j-1]*[r[i]-(j-1)]$

    补充数组定义,$l[i]$表示左区间在$i$$i$列以左的区间总数,也就是前缀和,$r[i]$同理,代表右区间在$i$列及其以左的区间总数,依旧前缀和,这个都计算$i$及其以左的前缀和的原因其实还挺好理解的,毕竟你在从左向右转移嘛,$dp[i-1][j-1]$就是要在前i列再放一个1,$r[i]-(j-1)$就是现在可以放一的区间个数

    所以就是一个放1,一个不放1两种情况

    接下来处理左区间,先上式子吧,$dp[i][j]=dp[i][j]*A_{i-j-l[i-1]}^{l[i]-l[i-1]}$,关于这个排列数,其实就是你现在一共有$i-j-l[i-1]$个位置可以放1,而你需要放$l[i]-l[i-1]$个一,那为什么不是组合数是排列数呢?举个例子,一共要选$x$列放1,其中对于第$p$行和第$q$行,你都在第$o$列放一,当然不是同一种情况,感性理解一下,当然就是排列数

    这道题很拓宽思路,以后又可以有一种新的思路

     1 #include<iostream>
     2 #include<cstdio>
     3 #define maxn 3010
     4 #define mod 998244353
     5 #define int long long
     6 using namespace std;
     7 int n,m;
     8 int zuo[maxn]/*左区间端点个数前缀和*/,you[maxn]/*右区间端点个数前缀和*/,jc[maxn],ny[maxn];
     9 int f[maxn][maxn];//右区间的左端点在第i列及其以左,已经放了j个1
    10 int ksm(int a,int b,int c)
    11 {
    12     int ans=1;  a=a%mod;
    13     while(b)
    14     {
    15         if(b&1)  ans=(ans*a)%mod;
    16         b=b>>1;  a=(a*a)%mod;
    17     }
    18     return ans%mod;
    19 }
    20 int A(int x,int y)
    21 {
    22     if(x<0)  return 1ll*0;
    23     if(y<0)  return 1ll*0;
    24     if(x<y)  return 1ll*0;
    25     if(y==0)  return 1ll*1;
    26     return (jc[x]*ny[x-y])%mod;
    27 }
    28 signed main()
    29 {
    30     scanf("%lld%lld",&n,&m);
    31     jc[0]=1;
    32     int ls=max(n,m);
    33     for(int i=1;i<=ls;++i)  jc[i]=(jc[i-1]*i)%mod;
    34     ny[ls]=ksm(jc[ls],mod-2,mod);
    35     for(int i=ls;i>=1;--i)  ny[i-1]=(ny[i]*i)%mod;
    36     for(int i=1;i<=n;++i)
    37     {
    38         int l,r;  scanf("%lld%lld",&l,&r);
    39         zuo[l]++;  you[r]++;
    40     }
    41     if(2*n>m)  {printf("0
    ");  return 0;}
    42     for(int i=1;i<=m;++i)  {zuo[i]+=zuo[i-1];  you[i]+=you[i-1];}
    43     f[0][0]=1;
    44     for(int i=1;i<=m;++i)
    45     {
    46         for(int j=0;j<=min(i,n);++j)
    47         {
    48             f[i][j]=(f[i][j]+f[i-1][j])%mod;
    49             if(j>0)  f[i][j]=(f[i][j]+f[i-1][j-1]*(you[i]-j+1))%mod;
    50             f[i][j]=(f[i][j]*A(i-j-zuo[i-1],zuo[i]-zuo[i-1]))%mod;
    51         }
    52     }
    53     printf("%lld
    ",f[m][n]);
    54     return 0;
    55 }
    View Code

    T3

    那个稍长的式子实际上是循环左移(不知道的问度娘吧)?是我见不多识不广了,那么对于异或来说,移位的影响其实很好解决,毕竟你不管是先移位再$xor$还是先$xor$再移位都可以得到正确答案,那对于中途$xor$一部分之后移位再继续$xor$,完全可以提前处理出来已知$a$数组的不同异或和,这样的话我们就可以得到$m-1$个不同的异或和,你的任务是选一个和$[0,2^n)$之间的数异或值最大,那我们完全可以把这些01串放到$trie$树上去跑,当然题目中那句对手会让结果尽量小也很重要,他提醒我们要计算最小值的最大值,对于某一位来说如果$trie$树上既有0又有1,那这一位一定无法作出贡献,如果两者只有其一,那一定会作出贡献,所以建出$trie$树之后,$dfs$跑一下就可以了

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define int long long
     5 #define maxm 100100
     6 #define maxx 32
     7 using namespace std;
     8 int n,m,tot,Ans,j;
     9 int a[maxm],deep[maxx*maxm];
    10 int trie[maxm*maxx][3];
    11 void jian(int x)
    12 {
    13     int p=0;
    14     for(int k=n-1;k>=0;--k)
    15     {
    16         int ch=(x>>k)&1;
    17         if(trie[p][ch]==0)  {trie[p][ch]=++tot;  deep[trie[p][ch]]=k;}
    18         p=trie[p][ch];
    19     }
    20 }
    21 void dfs(int x,int w)
    22 {
    23     if(trie[x][0]&&trie[x][1])  {dfs(trie[x][0],w);  dfs(trie[x][1],w);}
    24     else if(!trie[x][0]&&trie[x][1])  dfs(trie[x][1],w+(1<<deep[trie[x][1]]));
    25     else if(trie[x][0]&&!trie[x][1])  dfs(trie[x][0],w+(1<<deep[trie[x][0]]));
    26     else if(!trie[x][0]&&!trie[x][1])
    27     {
    28         if(w==Ans)  j++;
    29         else if(w>Ans)  {Ans=w;  j=1;}
    30         return ;
    31     }
    32 }
    33 signed main()
    34 {
    35     scanf("%lld%lld",&n,&m);
    36     for(int i=1;i<=m;++i)  {int x;  scanf("%lld",&x);  a[i]=a[i-1]^x;}
    37     for(int i=0;i<=m;++i)
    38     {
    39         int ls=1<<n;
    40         int ans=((2*a[i])/ls+2*a[i])%ls;
    41         ans=ans^a[m]^a[i];  jian(ans);
    42     }
    43     dfs(0,0);
    44     cout<<Ans<<endl<<j<<endl;
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    PHP 反射API
    wamp下mysql错误提示乱码的解法
    PDO、PDOStatement、PDOException
    PHP 常用函数
    TCP/IP
    centOS7+mariadb+Nginx+PHP7.0 安装
    php中引用&的真正理解-变量引用、函数引用、对象引用
    cgi fastcgi php-cgi php-fpm
    03 : linux判断服务器是虚拟机还是物理机
    02 :history命令显示日期-时间-登录IP-用户名
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11291076.html
Copyright © 2020-2023  润新知