Codeforces Round #662 (Div. 2)(A->D(dp))

A:http://codeforces.com/contest/1393/problem/A

解析:

猜的,没看懂题意。

#include <bits/stdc++.h>
#include<stdlib.h>
using namespace std;
typedef long long ll;
const int N=100010;
int a[N],b[N],f[N*2];
bool c[N*2];
map<int,int> m;
int find(int x)
{
  if(f[x]!=x) f[x]=find(f[x]);
  return f[x];
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n;
        cin>>n;
        cout<<n/2+1<<endl;
    }
}

B:http://codeforces.com/contest/1393/problem/B

题意:

给出N个长度已给出的木板,接下来进行增加/减少对应长度木板的操作(减少的前提是对应长度存在)

问是否能组成一个正方形+一个长方形(可为正方形)

解析:

记录两个值,出现次数为4的有几个,出现次数为2的有几个。

出现次数为4,记录后马上清0。

本解法达到了这么一个目的:

比如:1  1  1  1  1  1  2  2

f2=3

f4=1

f4中包含了一个f2。

具体的看注释吧:

#include<iostream>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int a[maxn];
int main()
{
    int n;
    cin>>n;
    int f2=0,f4=0;
    map<int,int>m;
    for(int i=1;i<=n;i++)
    {
        int g;
        cin>>g;
        m[g]++;
        if(m[g]==4)
            f4++,m[g]=0;  
        if(m[g]==2)
            f2++;  //所以f4里包含了一个f2,最后要特殊处理
    }
    int q;
    cin>>q;
    while(q--)
    {
        char ch;
        int h;
        cin>>ch>>h;
        if(ch=='+')
        {
            m[h]++;
            if(m[h]==4)
                f4++,m[h]=0;
            if(m[h]==2)
                f2++;    
        }
        else
        {
            m[h]--;  
            if(m[h]==-1)  //-1了,说明这个m[h]之前为0,那么之前就是为4,所以-1后,变成3即可。
                m[h]=3;
            if(m[h]==3)  //既然变成了3,说明之前为4,那么f4--
                f4--;
            if(m[h]==1)    //之前为2,所以f2--
                f2--;
        }
        if(f4>=2||(f4==1&&f2>=3))  //f4中包含了一个f2,所以f2需要多一个才能组成长方形
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    
}

C:http://codeforces.com/contest/1393/problem/C

构造+贪心+公式

题意:

n个蛋糕,编号对应所属类型。怎么样排序,使得相同类型蛋糕的间隔的最小值最大。求这个值。

解析:

很明显,贪心,要想最小值最大,那么同类型之间要尽可能地插入其他类型蛋糕,而且在这些间隔中,要平均地插。

那么首要起决定性作用的,是出现次数最多的那个。

比如:

1  1  1  1  2  3  4

有:1  2  1  3  1  4  1

如果出现最多次数的类型有多个:

1  1  1  1  2  2  2  2  3  4  5  6  7  8

有:1  2 (3,4)  1  2   (5,6)  1  2 (7,8)  1  2

既,出现最多的这些类型,每个取一个依次放,做为隔板,其他的平均往里插即可。

那么根据此,可以得到公式:

maxx为出现次数最多的次数,num为几个同maxx

(num-1)+(n-num*maxx)/(maxx-1)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<map>
#include<map>
using namespace std;
typedef long long ll;
const int mod=60;
const int maxn=1e5+7;
int l[maxn],r[maxn];
int a[maxn];
int b[8*maxn];
int vis[maxn];
ll c[maxn],d[maxn];
int pos[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
    //    memset(vis,0,sizeof(vis));
        int maxx=0;
        map<int,int>m;
        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            m[x]++;
            maxx=max(maxx,m[x]);
        }
        int num=0;
        for(int i=1;i<maxn;i++)
        {
            if(m[i]==maxx)
            {
                num++;
            }
        }
        cout<<num-1+(n-num*maxx)/(maxx-1)<<endl;
    }
}

D:https://codeforces.com/contest/1393/problem/D

题意:

问n*m的矩阵中,有多少个如图菱形(单个字符也算)

解析:参考自:

https://blog.csdn.net/hzf0701/article/details/107875485?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159696442619724848336941%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=159696442619724848336941&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-8-107875485.pc_first_rank_v2_rank_v28&utm_term=Codeforces+Round+%23662&spm=1018.2118.3001.4187

定义dp[i][j],表示以(i,j)为最底端的菱形的个数

对于(i-1,j)这个点,已经被(i-2,j)所维护,不必再看。

以(i,j)为底的菱形,它的扩大取决于标注的另外三个点,能扩多大,又取决于这三个点至少能够延伸多少,所以要对它们取min()

转移方程:

dp[i][j]=1;

dp[i][j]+=min(min(dp[i-1][j-1],dp[i-1][j+1]),dp[i-2][j]);

#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<map>
#include<map>
using namespace std;
typedef long long ll;
const int mod=60;
const int maxn=1e5+7;
int l[maxn],r[maxn];
int a[maxn];
int b[8*maxn];
int vis[maxn];
ll c[maxn],d[maxn];
int pos[maxn];
const int maxn2=2e3+10;
char mp[maxn2][maxn2];
int dp[maxn2][maxn2];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
            cin>>mp[i][j];
    }
    int sum=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            dp[i][j]=1;
            if(i>=2&&j>=1&&j<m-1&&mp[i][j]==mp[i-1][j-1]&&mp[i][j]==mp[i-1][j+1]&&mp[i][j]==mp[i-2][j]&&mp[i][j]==mp[i-1][j])
            {
                dp[i][j]+=min(min(dp[i-1][j-1],dp[i-1][j+1]),dp[i-2][j]);
                
            }sum+=dp[i][j];
        //    cout<<dp[i][j]<<' ';
        }
    }
    cout<<sum<<endl;
}

 

posted @ 2020-08-09 00:18  liyexin  阅读(184)  评论(0编辑  收藏  举报