zoukankan      html  css  js  c++  java
  • Codeforces Round #451 Div. 2 C D E

    C。Phone Numbers

    之前没有做过字典树……感觉这个题字典树也能做……就拿来练一练字典树……板子好多地方写的都不够好,还需要继续改……

    emmm这个……卡了好久啊……不过好在还是debug出来了……orz

    虽然是处理后缀的问题,但是只需要reverse一下就可以变成前缀问题了2333333,然后每一次的字符串都插进去,最后从叶子到根遍历输出就可以了……

    不过我好像……连叶子到根的遍历都写不好呜呜呜……ps:这里只是为了用trie而用trie……其实用map维护一下直接暴力求解就可以……

    //trie树
     /*1. 字符串检索
       2.词频统计
       3.字符串排序  先序遍历
       4.前缀匹配
       */
    #include<bits/stdc++.h>
    using namespace std;
    const int MAX=10;
    string number;
    int now,cnt=0;
    int crt[25];
    struct trie{
        trie *next[MAX];
        int v=0;
    };
    trie *root[20];
    trie* creat_trie()
    {
        trie *temp=(trie*)malloc(sizeof(trie));
        for(int i=0;i<10;i++)
         temp->next[i]=NULL;
        return temp;
    }
    void insert_trie(trie *r,string s,int k)
    {
        trie *p=r;
        for(int i=0;i<s.length();i++)
        {
            int id=s[i]-'0';
            if(p->next[id]==NULL)
                p->next[id]=creat_trie();
            p=p->next[id];
        }
    }
    void search_trie(trie *r,int k)
    { 
        int c=0;
        for(int i=0;i<10;i++)
        {
          if(r->next[i]!=NULL)
          {
           c++;
           search_trie(r->next[i],k); 
          }
        } 
        if(c==0&&r->v!=-1) {
        crt[k]++;
        r->v=-1;
       }
    }
    void print(trie *r)
    {
        if(r->v==-1)
        { 
           reverse(number.begin(),number.end());
           cout<<number<<" ";
           reverse(number.begin(),number.end());
           return ;
        }
          for(int i=0;i<10;i++)
       {
           if(r==root[now])
           number="";
           if(r->next[i]!=NULL)
           {
         number+=char(i+'0');
           print(r->next[i]);
           number=number.substr(0,number.length()-1);
        }
       }
       
    }
    int main()
    {
        int n,m;
        map<string,int>e;
        string a,b;
        cin>>n;
        memset(crt,0,sizeof(crt));
        for(int i=0;i<=n;i++)
          root[i]=creat_trie();
        while(n--)
        {
            cin>>a;
            if(e[a]==0)
             e[a]=++cnt;
            cin>>m;
            now=e[a];
            while(m--)
            {
                cin>>b;
                reverse(b.begin(),b.end());
                insert_trie(root[now],b,now);
            }
        }
        cout<<e.size()<<endl;
        map<string,int>::iterator it;
        for(it=e.begin();it!=e.end();it++)
        {
            cout<<it->first<<" ";
            now=it->second;
            search_trie(root[now],now);
            cout<<crt[now]<<" ";
            print(root[now]);
            cout<<endl;
        }
        return 0;
    }

    (好像还有个后缀树啥的……emmmm还没有学习……码着先)

    D。Alarm Clock

    是个前缀和+贪心的问题么……看大佬简洁的代码是那么处理的,自己搞得太复杂了……还……好多bug

    需要好好想想哪些用前缀和处理更简洁,比如像这种多长时间内的,多大长度内的问题,可以考虑用前缀和?

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll n,m,k,b;
    ll a[1000005];
    int main()
    {
        cin>>n>>m>>k;
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
        {
          cin>>b;
          a[b]=1;     
        }
        int ans=0;
        for(int i=1;i<=m;i++)
        {
            a[i]+=a[i-1];
            if(a[i]>=k)
            {
                ans+=(a[i]-(k-1));
                a[i]=k-1;
            }
        }
        for(int i=m+1;i<1e6+5;i++)
        {
            a[i]+=a[i-1];
            b=a[i]-a[i-m];
            if(b>=k)
            {
                ans+=(b-k+1);
                a[i]=a[i-m]+k-1;
            }
        }
        cout<<ans<<endl;
        return 0;
    }

    E。Squares and not squares

    想着暴力dfs我也是傻了……orz

    依旧还是贪心,这次题……好多贪心……

    2种情况……为平方数的个数m<=n/2,ans=(n/2-m)个非平方数变成平方数和的最小值

                                                 m>=n/2,ans=(m-n/2)个平方数变为非平方数和的最小值(非0值每个数只需要+1,0需要+2)//注意0需要特判,良心样例有没有啊!

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll n,a[200005],ans;
    ll b[200005];
    int main()
    {
        cin>>n;
        int cnt=0,cnt0=0,cnt1=0;
        for(int i=0;i<n;i++)
        {
         cin>>a[i]; 
         ll c=sqrt(a[i]);
         ll minn=min(a[i]-pow(c,2),pow(c+1,2)-a[i]);
         b[i]=minn;
         if(b[i]==0)
          cnt++;
        if(a[i]==0) cnt0++;
        }
        if(cnt>=n/2&&cnt0<=n/2) ans=cnt-n/2;
        else if(cnt0>n/2)
            ans=cnt-cnt0+2*(cnt0-n/2);
        else 
        {
            ans=0;
               sort(b,b+n);
            for(int i=0;i<n/2;i++)
               ans+=b[i]; 
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    leetcode 213. 打家劫舍 II JAVA
    leetcode 48. 旋转图像 java
    leetcode 45. 跳跃游戏 II JAVA
    leetcode 42. 接雨水 JAVA
    40. 组合总和 II leetcode JAVA
    24. 两两交换链表中的节点 leetcode
    1002. 查找常用字符 leecode
    leetcode 23. 合并K个排序链表 JAVA
  • 原文地址:https://www.cnblogs.com/Egoist-/p/8094416.html
Copyright © 2011-2022 走看看