首页 > 其他 > 详细

Codeforces Round#402(Div.1)掉分记

时间:2017-02-27 00:45:32      阅读:397      评论:0      收藏:0      [点我收藏+]

哎,今天第一次打div1 感觉头脑很不清醒。。。

看到第一题就蒙了,想了好久,怎么乱dp,倒过来插之类的...突然发现不就是一道sb二分吗.....sb二分看了二十分钟........

然后第二题看了一下,感觉太码农了不可做,然后就cd逛一逛。

突然觉得c可做,就做了一下,交上去wa了,发现有情况没考虑。

这下又滚回了b,结果又没写完......

gg  2040 -83 ->1957

-----------------------------------------------我似分割线啊

A.String Game

题意:有一个n个字符组成的字符串,并给定它的一个子串。调皮的小孩一个人会按照时间顺序每一秒删掉其中一个字符,求一个最迟的时间,使得给定的串仍然是剩下的字符串的子串。n<=200000

题解:别想太多,直接二分答案,On 来check一下。

复杂度nlogn

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long longh
#define INF 2000000000
#define MAXN 200000
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-) f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();}
    return x*f;
} 

char s2[MAXN+5];
char s[MAXN+5];
int n,m;
int a[MAXN+5];
int p[MAXN+5];

bool check(int x)
{
    int j=1;
    for(int i=1;i<=n&&j<=m;i++)
        if(p[i]>x&&s[i]==s2[j]) ++j;
    if(j>m) return true;
    return false;
}

int main()
{
    scanf("%s",s+1);
    scanf("%s",s2+1);
    n=strlen(s+1);m=strlen(s2+1);
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        p[a[i]]=i;
    }
    int l=0,r=n,mid,ans;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid)) ans=mid,l=mid+1;
        else r=mid-1;    
    }
    cout<<ans;
    return 0;
} 

B.Bitwise Formula

题意:给定n个变量的定义,每个变量都是m位的二进制数,你可以选择一个数,这些变量在定义的时候可能会用到之前的变量和你选择的数,最后的贡献为所有的变量大小之和。你要分别在贡献最大和最小的情况下,选择最小的数字。

n<=5000 m<=1000

题解:贪心。对每一位分别check(),枚举那一位选择1或者0,算一下这一位上的贡献,确定取值即可。复杂度nm

我的代码丑

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<map>
#define ID 20170226
#define ll long long
using namespace std;
inline int read()
{
   int  x=0,f=1;char ch=getchar();
   while(ch<0||ch>9){if(ch==-) f=-1;ch=getchar();}
   while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();}
   return x*f;
}
string st,st2,name;
map<string,int> mp;
char s[10000];
int mark[5005][3];
int x[5005][1005],x2[5005][1005];
int n,m,ans[5005];
char op[5005];
int f[5005];

int check(int j,int def)
{
    int x1,y1,tot=0;
    for(int i=1;i<=n;i++)
    {
        if(mark[i][1]==ID) x1=x[i][j];
        else if(mark[i][1]==-1) x1=def;
        else x1=f[mark[i][1]];
        if(mark[i][2]==ID)y1=x2[i][j];
        else if(mark[i][2]==-1) y1=def;
        else y1=f[mark[i][2]];
       // cout<<i<<" "<<j<<" "<<x1<<" "<<y1<<endl;
        if(op[i]==O) x1=x1|y1;
        if(op[i]==A) x1=x1&y1;
        if(op[i]==X) x1=x1^y1;
        f[i]=x1;tot+=x1;
    }
    return tot;
}

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
    {
        int nown=0;
        cin>>name;mp[name]=i;
        scanf("%s",s);cin>>st;
        if(getchar()!=\n)
        {
            scanf("%s",s);
            cin>>st2;
            if(st2=="?") mark[i][2]=-1;
            else if(st2[0]>=0&&st2[0]<=9)
            { mark[i][2]=ID;for(int j=0;j<m;j++) x2[i][j]=st2[j]-0;}
            else mark[i][2]=mp[st2];
            op[i]=s[0];
        }
        else mark[i][2]=ID,op[i]=O;
        if(st=="?") mark[i][1]=-1;
        else if(st[0]>=0&&st[0]<=9)
        { mark[i][1]=ID;for(int j=0;j<m;j++) x[i][j]=st[j]-0;}
        else mark[i][1]=mp[st];

    }
    for(int i=0;i<m;i++)
    {
        int x=check(i,0);int y=check(i,1);
        if(x>y) printf("1");
        else if(x==y) printf("0");
        else printf("0"),ans[i]=1;
    }
    puts("");
    for(int i=0;i<m;i++)printf("%d",ans[i]);
    return 0;
}

C.给定一棵trie树,你可以删掉其中一个深度的点,求重建的trie树最少有多少个点以及最少时删掉哪一个深度。

题解:如图:

 

技术分享

 我们可以发现,删掉一个深度之后减少的点的数量不仅仅是这个深度的节点的数量,还包括这个 深度的爸爸相同(1)的点 (2,3) 的相同字母(c) 的边指向的点(5,4)

这个例子中4和5可以合成一个点,实际上减少的部分还包括了4和5的相同字母的边指向的点,以此类推。

所以我们可以考虑在dfs的时候直接暴力算每个点的可合并孙子的个数,并且加入对应深度的答案当中,然后递归下去做。

具体实现见代码(向cf的一些dalao学习的)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<map>
#define MAXN 600000
using namespace std;
inline int read()
{
   int  x=0,f=1;char ch=getchar();
   while(ch<0||ch>9){if(ch==-) f=-1;ch=getchar();}
   while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();}
   return x*f;
}


int n,m;
int c[MAXN+5][26];
char ch;
int sum[MAXN+5];

int newnode(int x)
{
    for(int i=0;i<26;i++) c[m][i]=c[x][i];
    return m++;
}

void merge(int&x,int y,int dep)
{
    if(!x||!y){x+=y;return;}
    x=newnode(x);++sum[dep];
    for(int i=0;i<26;i++)merge(c[x][i],c[y][i],dep);
}

void dfs(int x,int dep)
{
    sum[dep-1]++;int nown=0;m=n+1;
    for(int i=0;i<26;i++,nown=0)
        for(int j=0;j<26;j++)
            if(c[c[x][j]][i])
                merge(nown,c[c[x][j]][i],dep);
    for(int i=0;i<26;i++) if(c[x][i]) dfs(c[x][i],dep+1);
}

int main()
{
    n=read();
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read();scanf("%c",&ch);
        c[u][ch-a]=v;
    }
    dfs(1,1);int ans=1;
    for(int i=1;i<=n;i++) if(sum[i]>sum[ans]) ans=i;
    printf("%d\n%d",n-sum[ans],ans);
    return 0;
}

D.还不会,挖个坑

Codeforces Round#402(Div.1)掉分记

原文:http://www.cnblogs.com/FallDream/p/codeforces402.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!