zoukankan      html  css  js  c++  java
  • 2019.8.1考试反思

    八月开了一个完美的好头倒数加倍快乐加倍

    日常看一遍题,觉得都不可做但是暴力分很好拿,于是快乐开始撕烤&暴力。

    T1一看40分白送,然后想了想,和之前一道题排序非常想,排序是01串判断位置,思想还是差不多的。

    然后我脑子长了锈了死活转不过弯来

    看了看T2,手%样例后发现两个区间之间的地方其实是不能放的。

    那么每个小区间都可以影响大区间,处理一下每个-1,码完收工。

    T3貌似暴力可以骗40分?前缀和之后处理异或即可,用大暴力和暴力对拍。

    T1并没有继续从之前堵住的地方绕出来。

    然后就结束了。

    题解部分

    T1:

    明显和排序异曲同工,排序是二分查找位置,将其转化成01串,而这道题明显可以看作是26次区间赋值

    然后因为常数太鸡儿大被卡掉,然后循环展开可过我估计和T60的我没有什么关系

    换一种思路,如果这一整个区间都是一样的,那么我们把它赋成对应的值,这样就避免了遍历整棵树

    然后区间查询个数之后区间赋值 我并不会证明复杂度QwQ

    某树袋熊双手上下摇摆:这样你在考场上就快乐的拿到了100分(雾)的好成绩

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define reg register
     6 #define ls(k) k<<1
     7 #define rs(k) k<<1|1
     8 using namespace std;
     9 int const maxn=1e5+10;
    10 struct node{int l,r,lz,w;}t[maxn*4];
    11 int n,m,cnt[27];
    12 char ch[maxn];
    13 void debug(){for(int i=1;i<=26;i++) cout<<i<<" "<<cnt[i]<<endl;}
    14 inline void build(int l,int r,int k)
    15 {
    16     t[k].l=l,t[k].r=r;
    17     if(l==r)
    18     {
    19         t[k].w=ch[l]-'a'+1;
    20         return ;
    21     }
    22     int mid=l+r>>1;
    23     build(l,mid,ls(k));
    24     build(mid+1,r,rs(k));
    25     if(t[ls(k)].w==t[rs(k)].w) t[k].w=t[ls(k)].w;
    26 }
    27 inline void query(int l,int r,int k)
    28 {
    29     if(l<=t[k].l&&r>=t[k].r&&t[k].w)
    30     {
    31         cnt[t[k].w]+=t[k].r-t[k].l+1;
    32         return ;
    33     } 
    34     if(t[k].w) t[ls(k)].w=t[k].w,t[rs(k)].w=t[k].w;
    35     int mid=t[k].l+t[k].r>>1;
    36     if(mid>=l) query(l,r,ls(k));
    37     if(mid<r) query(l,r,rs(k));
    38 }
    39 inline void add(int l,int r,int k,int pos)
    40 {
    41     if((l<=t[k].l&&r>=t[k].r)||t[k].w==pos)
    42     {
    43         t[k].w=pos;
    44         return ;
    45     }
    46     if(t[k].w) t[ls(k)].w=t[k].w,t[rs(k)].w=t[k].w;
    47     int mid=t[k].l+t[k].r>>1;
    48     if(mid>=l) add(l,r,ls(k),pos);
    49     if(mid<r) add(l,r,rs(k),pos);
    50     if(t[ls(k)].w==t[rs(k)].w) t[k].w=t[ls(k)].w;
    51     else t[k].w=0;
    52 }
    53 inline void ask(int k)
    54 {
    55     if(t[k].w)
    56     {
    57         for(int i=t[k].l;i<=t[k].r;i++) printf("%c",t[k].w+'a'-1);
    58         return ;
    59     } 
    60     ask(ls(k));ask(rs(k));
    61 }
    62 int main()
    63 {    
    64     scanf("%d%d",&n,&m);
    65     scanf("%s",ch+1);
    66     build(1,n,1);
    67     for(reg int i=1;i<=m;i++)
    68     {
    69         for(int i=1;i<=26;i++) cnt[i]=0;
    70         int opt,l,r;
    71         scanf("%d%d%d",&l,&r,&opt);
    72         query(l,r,1);
    73         //debug();
    74         if(opt)
    75         {    
    76             int tmp=l;
    77             for(reg int j=1;j<=26;j++)
    78             {
    79                 if(!cnt[j]) continue;
    80                 add(tmp,tmp+cnt[j]-1,1,j);
    81                 tmp+=cnt[j];
    82             }
    83         }
    84         else 
    85         {
    86             int tmp=l;
    87             for(reg int j=26;j>=1;j--)
    88             {
    89                 if(!cnt[j]) continue;
    90                 add(tmp,tmp+cnt[j]-1,1,j);
    91                 tmp+=cnt[j];
    92             }
    93         }
    94     }
    95     ask(1);
    96     return 0;
    97 }
    View Code

    T2:

    又是一个神仙dp,%%%Smily考场A掉TQLOTZ

    我本来以为是组合数,码出来的**被我考试后脑子hack,天知道我怎么能这么想。

    首先读题可以发现这道题和行几乎没有什么关系,然后我们用列转移。

    设$ f[i][j] $为到达第 $i$ 列时左侧有$j$个右区间放了,$L$ 为左区间个数前缀和,$R$ 为右区间个数前缀和

    当前状态可以从右区间没有放以及放了转移。

    即 $f[i][j]=f[i-1][j]+f[i-1][j-1]*(R[i]-j+1)$

    再考虑左区间。

    我们可以得到,每一个包含在大区间的小区间都使对大区间中可选择的位置减少1个,所以用它来计算左区间贡献。

    并不需要担心负数,因为一旦出现负数那么代表状态不合法。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define ll long long
     5 using namespace std;
     6 int const maxn=3010;
     7 int const mod=998244353;
     8 ll n,m,l[maxn],r[maxn],L[maxn],R[maxn],f[maxn][maxn];
     9 int main()
    10 {
    11     scanf("%lld%lld",&n,&m);
    12     for(int i=1;i<=n;i++) scanf("%lld%lld",&l[i],&r[i]),L[l[i]]++,R[r[i]]++;
    13     for(int i=1;i<=m;i++) L[i]+=L[i-1],R[i]+=R[i-1];
    14     f[0][0]=1;
    15     for(int i=1;i<=m;i++)
    16     {
    17         f[i][0]=f[i-1][0];
    18         for(int j=1;j<=i;j++) (f[i][j]+=f[i-1][j]+f[i-1][j-1]*(R[i]-j+1)%mod)%=mod; //右区间
    19         for(int k=0;k<=i;k++)
    20             for(int j=L[i-1];j<L[i];j++)
    21                 (f[i][k]*=(i-k-j))%=mod; //左区间
    22     }
    23     printf("%lld",f[m][n]);
    24 }
    View Code

    T3:

    可以很明显看出来枚举断点来判断从而骗到40分然后我因为赋值的原因少了24TAT

    首先它的柿子是一个类似于逻辑左移的东西,然后对手有m+1种不同的异或方案。

    建一棵$01trie$进行$dfs$,因为对手总会尽量使你的最终结果更低,所以有两种情况:

    1,如果当前节点有两个儿子,那么无论这一位是什么,对手都能把它异或成0,不考虑贡献向下走

    2,只有1个儿子,那么我们选择另一个就可以使这一位有贡献,继续沿着$trie$走

    最终到叶子就是答案,可以看到一开始的柿子对答案并没有影响,因为无论如何都能得到所有的数

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<map>
     5 using namespace std;
     6 int const maxn=1e5+10;
     7 int n,m,a[maxn],sum[maxn],yh[maxn],trie[30*maxn][2],tot,imax;
     8 map<int,int>mp;
     9 void insert(int x)
    10 {
    11     //cout<<x<<endl;
    12     int rt=0;
    13     for(int i=1<<(n-1);i>0;i>>=1)
    14     {
    15         int w=(x&i)?1:0;
    16         if(!trie[rt][w]) trie[rt][w]=++tot;
    17         rt=trie[rt][w];
    18         //cout<<x<<" "<<w<<" "<<rt<<endl;
    19     }
    20     //cout<<endl;
    21 }
    22 void dfs(int x,int i,int now)
    23 {
    24     //cout<<x<<" "<<i<<" "<<now<<endl;
    25     if(i==0)
    26     {
    27         imax=max(imax,now);
    28         mp[now]++;
    29         return ;
    30     }
    31     if(!trie[x][0]&&trie[x][1])
    32     {
    33         dfs(trie[x][1],i-1,(now|(1<<i-1)));
    34     } 
    35     if(trie[x][0]&&!trie[x][1])
    36     {
    37         dfs(trie[x][0],i-1,(now|(1<<i-1)));
    38     } 
    39     if(trie[x][0]&&trie[x][1])
    40     {
    41         dfs(trie[x][0],i-1,now);
    42 
    43         dfs(trie[x][1],i-1,now);
    44     } 
    45 }
    46 int main()
    47 {
    48     //freopen("da.in","r",stdin);
    49     //freopen("ans.txt","w",stdout);
    50     scanf("%d%d",&n,&m);
    51     for(int i=1;i<=m;i++) scanf("%d",&a[i]);
    52     for(int i=1;i<=m;i++) sum[i]=sum[i-1]^a[i];
    53     int s=0;
    54     for(int i=0;i<=m;i++)
    55     {
    56         int now=0;
    57         a[i]=(2*a[i]/(1<<n)+2*a[i])%(1<<n);
    58         s^=a[i];
    59         now=s^sum[m]^sum[i];
    60         insert(now);
    61     }
    62     dfs(0,n,0);
    63     printf("%d
    %d",imax,mp[imax]);
    64 }
    View Code

    40+0+16比较玄学分数,暴力打满100是rank7。

    看了一下,现在rank51,非常危险的位置。

    以前总觉得自己并不差,一次考不好下回可以考回来。

    但是连续的排名靠后就暴露了问题。

    正解接近但码不出来,暴力总在细节出错,思路明明接近却无法灵活变通。

    非常致命。

    如果连暴力都打不满,如果考试持续倒数,如果在NOIP就退役,这不是我想要的结果。

    目标是停课,然后省队,然后拿政策。

    我答应了的事情就要做到。

  • 相关阅读:
    YUI: Effects Widgets
    提高Web页面的性能(一)
    textindent 隐藏文字时出现的 outline 问题
    通过 Dom 方法提高 innerHTML 性能
    IE8 beta1 中的 CSS 属性
    推荐的 CSS 书写顺序
    来自经典论坛的javascript小小考题
    IE5 到 IE8 的 CSS 兼容列表
    backgroundclip 与 backgroundorigin 的一则运用
    收集整理的对#!bin/sh的认识
  • 原文地址:https://www.cnblogs.com/MouDing/p/11286974.html
Copyright © 2011-2022 走看看