10.17考试总结

来源:互联网 发布:读图软件免费下载 编辑:程序博客网 时间:2024/06/01 07:26

1.购买板凳(100/100)

    题目大意:有许多人在某时刻来,会占人数座,直到某时刻走求最少需要多少座椅;

       感想:差分,记录每个时刻的进出人数;

# include <cstdio># include <iostream># include <cctype># include <cstring># include <string># include <cmath># include <algorithm>using namespace std;typedef long long ll; int Read(){int f=1,i=0;char ch;for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());if(ch=='-'){f=-1;ch=getchar();}for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';return i*f;}struct node{int l,r,num;}a[100005];char s[10];int n,m,str[10005],end[10005];int main(){n=Read();for(int i=1;i<=n;++i){a[i].num=Read();scanf("%s",s);for(int j=0;j<strlen(s);++j){if(s[j]==':') continue;a[i].l=a[i].l*10+(s[j]-'0');}str[a[i].l]+=a[i].num;scanf("%s",s);for(int j=0;j<strlen(s);++j){if(s[j]==':') continue;a[i].r=a[i].r*10+(s[j]-'0');}end[a[i].r]+=a[i].num;}int ans=0,maxx=0;for(int i=0;i<2400;++i){if(!str[i]&&!end[i]) continue;ans=ans+str[i]-end[i];if(ans>maxx) maxx=ans;}    printf("%d\n",maxx);}

2.新排序(0/100)

    题目大意:给一个数组,每次删去一些数,这些数要么比它左边数小,要么比右边数大,最后输出剩下的数;

      感想:本题大概看了一眼,感觉好像挺简单,然后随便模拟一下,再用链表维护,感觉很稳,结果wa了,具体原因也不知道;

   

# include <cstdio># include <iostream># include <cctype># include <cstring># include <string># include <cmath># include <algorithm># include <queue>using namespace std;typedef long long ll; int Read(){int f=1,i=0;char ch;for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());if(ch=='-'){f=-1;ch=getchar();}for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';return i*f;}const int INF=1e9+7;int l[100005],r[100005],a[100005],b[100005];int n,m,t,cnt;bool vis[100005];int main(){t=Read();while(t--){n=Read();for(int i=1;i<=n;++i) a[i]=Read();for(int i=1;i<=n;++i){l[i]=i-1;r[i]=i+1;}a[0]=-1;a[n+1]=INF;queue<int >qa,qb,qc;for(int i=1;i<=n;++i)     if(a[i]<a[i-1]||a[i]>a[i+1]) qa.push(i);memset(vis,0,sizeof(vis));while(!qa.empty()){while(!qa.empty()){int nowp=qa.front();qa.pop();qb.push(nowp);if(a[l[nowp]]<=a[nowp]&&l[nowp]>=1) qc.push(l[nowp]);if(a[r[nowp]]>=a[nowp]&&r[nowp]<=n) qc.push(r[nowp]);}while(!qb.empty()){int nowp=qb.front();qb.pop();vis[nowp]=1;l[r[nowp]]=l[nowp];r[l[nowp]]=r[nowp];}while(!qc.empty()){int nowp=qc.front();qc.pop();if(!vis[nowp]&&(a[l[nowp]]>a[nowp]||a[r[nowp]]<a[nowp])) qa.push(nowp);}}cnt=0;for(int i=1;i<=n;++i) if(!vis[i]) b[++cnt]=a[i];cout<<cnt<<endl;for(int i=1;i<=cnt;++i) cout<<b[i]<<" ";cout<<endl;}}

  算了,说一下正解思想,每次找出那一段段的单减序列,删除里面点,在从剩下点中继续找,直到没有;

3.豆豆游戏(0/100)

    题目大意:给一串01字符串,每次可以插入一个0or1,每3个及以上连续相同点可以消去,求消完最少需要几次操作;

       感想:状态已经差不多推出来了,然后时间不够打了个暴力,然后发现应该缩点,最后还是想打暴力算了,结果败在string调试上,果然搜索姿势不够;然后说正解:显而易见只能一块块消,于是缩点,有num记录点权,然后飞[i][j]定义为i到j区间最小值,考虑转移方程:

       1.f[i][j]=3-num[i],i==j;不用说吧。

       2.f[i][j]=f[i][k],f[k+1][j];i<=k<j;分开成两个单独区间消除;

       3.f[i][j]=f[i+1][j-1]+max(3-num[i]-num[j]);当j与i的数相同时;

       4.f[i][j]=f[i+1][k-1]+f[k+1][j-1];满足3的条件,同时num[i]+num[j]<4,且num[k]=1;

       前三点没什么好说的,解释第4点,首先给个样例:1100110010110100110011;大多数人会说是2,但真的是吗?无非是把它分成11001100101和10100110011,每边放个0,可是当一边放完0后,宁一边的第一个1会一起消掉,于是不能用一个0消去了,所以答案不会是2;所以要使2端同时消掉就要保证其中一边不会和中间的数先消掉,所以num【k】==1,num[i]+num[j]<4;

# include <cstdio># include <iostream># include <cctype># include <cstring># include <string># include <cmath># include <algorithm>using namespace std;typedef long long ll; int Read(){int f=1,i=0;char ch;for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());if(ch=='-'){f=-1;ch=getchar();}for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';return i*f;}int f[205][205],n,m,cnt,num[205];char s[205],t[205];int main(){int ctr;ctr=Read();while(ctr--){scanf("%s",s+1);int len=strlen(s+1);cnt=0;for(int i=1;i<=200;++i) num[i]=1;for(int i=1;i<=len;++i){if(s[i]!=s[i-1]) t[++cnt]=s[i];else num[cnt]++;}//for(int i=1;i<=cnt;++i) cout<<t[i]<<" ";//cout<<endl;memset(f,127,sizeof(f));for(int i=cnt;i;--i)    for(int j=i;j<=cnt;++j)    {    if(i==j)     {    f[i][j]=3-num[i];    continue;    }    if(t[i]==t[j])     {    f[i][j]=f[i+1][j-1]+max(0,3-num[i]-num[j]);    if(num[i]+num[j]<4)        for(int k=i+2;k<j;k+=2)            if(num[k]==1) f[i][j]=min(f[i][j],f[i+1][k-1]+f[k+1][j-1]);    }    for(int k=i;k<j;++k) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);    }cout<<f[1][cnt]<<endl;}}

感觉题目还是比较友善的,还是自己太蒟蒻了,只拿了100分,告诉我们要注意拿分策略,不要盲目;


原创粉丝点击