ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

swpu 训练周赛(4)

2021-04-16 21:00:31  阅读:174  来源: 互联网

标签:周赛 训练 vis int else ++ printf include swpu


A .Diverse Strings(div.3)

在这里插入图片描述

题意:

如果一个字符串是连续且不含有重复字母就输出Yes,否则输出No。

思路:

定义一个数组存储每一个字母出现的次数。找到ASCII码最大和最小的字母作为左右边界。从左到右遍历,如果有字母出现的次数不为1.则输出No.
否则输出Yes.(好好的签到题因为看不懂题目卡了20分钟,QQ翻译有毒(我一定好好学英语.))

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define N 1005
using namespace std;
int ans[N];
char sum[40];
int main()
{
    int n;
    string a;
    scanf("%d",&n);
    while(n--)
    {
        memset(ans,0,sizeof(ans));
        cin>>a;
        int maxx = 0,minn ='z'-'a';
        for(int i=0; i<a.length(); ++i)
        {
            ans[a[i]-'a']++;
            maxx = max(maxx,a[i]-'a');
            minn = min(minn,a[i]-'a');
        }
        bool flag =0;
        for(int i=minn; i<=maxx; ++i)
        {
            if(ans[i] != 1)
            {
                flag =1;
                break;
            }
        }
        if(flag)
            printf("No\n");
        else
            printf("Yes\n");
    }
    return 0;
}

B. Parity Alternated Deletions(Div.3)

在这里插入图片描述

题意:

给定n个数,对数组进行删除操作,即删除某个元素,但是删除操作必须以“奇偶奇偶奇偶…”的或者“偶奇偶奇偶奇…”的方式进行,问当不能进行删除操作的时候,所剩下的数的可能的最小值;

思路:

输入时分别记录奇数偶数的个数,如果奇数偶数个数相差小于等于1,则,可以删完。否则输出剩下的奇数(偶数)的和(排序由小到大遍历直到累加奇数偶数个数差个奇数(偶数))。

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main()
{
    int n, sum = 0;
    int x = 0, y = 0;
    cin >> n;
    for (int i = 0; i < n;i++)
    {
        scanf("%d", &a[i]);
        if(a[i]%2!=0)
            x++;
        else
            y++;
    }
    sort(a, a + n);
    if(x==y||abs(x-y)==1)
    {
        printf("0");
    }
    else if(x>y)
    {
        int m = x - y - 1;
        for (int i = 0; m != 0; i++)
        {
            if(a[i]%2!=0)
            {
                sum += a[i];
                m--;
            }
        }
        printf("%d", sum);
    }
    else
    {
        int m = y - x - 1;
        for (int i = 0; m != 0; i++)
        {
            if(a[i]%2==0)
            {
                sum += a[i];
                m--;
            }
        }
        printf("%d", sum);
    }
    return 0;
}

C.Two Merged Sequences(Div.3)

在这里插入图片描述

题意:

给定一个长度n的整数序列,让你把它分割成两个序列,第一个序列严格递增,第二个序列严格递减,空序列(长度为0)或者只含有一个元素既属于递增序列也属于递减序列,问是否能分割成这样的两个序列,不能输出"NO",否则输出"YES",分别输出递增序列长度,递增序列,递减序列长度,递减序列,空集输出0和空行;

思路:

一个数出现的次数如果为0次,自然不用考虑,如果为1次,则可以随意安排进递增数组或者递减数组,如果为两次,则放进另一个数组。如果大于2次,粉的数组就不可能单调。所以当一个数大于2次,就不可能分的正确的数组,应当输出No.如果每一个数出现的次数都小于等于2次,则输出排序后的两个数组(一个按递增排,一个递减排)。

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e6 + 10;
int n, x, k1, k2;
int cnt[N];
int a[N], b[N];
bool flag=false;
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d", &x);
        cnt[x]++;
        if(cnt[x]==1)
            a[k1++] = x;
        else if(cnt[x]==2)
            b[k2++] = x;
        else
            flag=true;
    }
    if(flag)
        printf("NO\n");
    else
    {
        printf("YES\n");
        sort(a, a + k1);
        sort(b, b + k2, cmp);
        printf("%d\n", k1);
        for (int i = 0; i < k1;i++)
            printf("%d ", a[i]);
        printf("\n");
        printf("%d\n", k2);
        for (int i = 0; i < k2;i++)
            printf("%d ", b[i]);
        printf("\n");
    }
    return 0;
}

D. Equalize Them All(div.3)

在这里插入图片描述

题意:

给定一个含n个整数的序列,你可以对他进行1.ai:=ai+|ai−aj|; 2.ai:=ai-|ai−aj|;不断的进行这两种操作中的一种,直到这个序列仅有一种元素,输出操作次数,及每次操作的种类(1或2)及i和j;

思路:

分析两种操作,如果将操作1对两个数中较小的数使用,两个数中较小的数会变为两个数中较大的数,如果将操作2对两个数中较大的数使用,两个数中较大的数会变为两个数中较小的数。该题要求最小次数,显然需要找到出现次数最多的数,将其他数变成它。

#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int n;
int a[N], vis[N];
int id,maxx;
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        vis[a[i]]++;
        if(vis[a[i]]>maxx)
        {
            maxx=vis[a[i]];
            id=i;
        }
    }
    printf("%d\n", n - maxx);
    for (int i = id - 1; i >= 1; i--)
    {
        if(a[i]>a[i+1])
            printf("2 %d %d\n", i, i + 1);
        else if(a[i]<a[i+1])
            printf("1 %d %d\n", i, i + 1);
        a[i]=a[i+1];
    }
    for (int i = id + 1; i <= n; i++)
    {
        if(a[i]>a[i-1])
            printf("2 %d %d\n", i, i - 1);
        else if(a[i]<a[i-1])
            printf("1 %d %d\n", i, i - 1);
        a[i]=a[i-1];
    }
    return 0;
}

E. Graph Without Long Directed Paths(Div.3)

在这里插入图片描述

题意:

给你一个无向图,让你把这个图变成有向图。这个有向图需要满足的是,从每一个结点出发到另一个结点。只能有一个路径长度。通俗讲,就是,如果A 结点 有一条路径到B 结点,那么B 结点就不能再有其他路径到其他结点去了。

思路:

分析题意,不能有>=2的路径,其实就是每个点的边,要不就是全部指向它,要不然就是全部从它出去。这样就不会有>=2的路径出现了.


```cpp
#include<iostream>
#include<cstring>
using namespace std;
const int N = 2e5+10;
int n, m, tot, cnt;
int head[N];
int vis[N];
int v[N]; 
struct node
{
    int to;
    int next;
} edge[N<<2];
void add(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
void dfs(int s,int tmp)
{
    if(!vis[s])
        vis[s] = tmp;
    else
        return;
    for(int i=head[s]; i!=-1; i=edge[i].next)
    {
        if(vis[s]==vis[edge[i].to]) 
        {
            cnt = 0;
            return;
        }
        if(vis[s]==1)
            dfs(edge[i].to,2);
        else
            dfs(edge[i].to,1);
    }
}
int main()
{
    cin>>n>>m;
    int i;
    tot = 1;
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
    for(i=0; i<m; i++)  
    {
        int u;
        scanf("%d %d",&u,&v[i]);
        add(u,v[i]);
        add(v[i],u);
    }
    cnt = 1;
    dfs(1, 1);
    if(!cnt)
        printf("NO\n");
    else
    {
        printf("YES\n");
        for(i=0; i<m; i++)
        {
            if(vis[v[i]]==1)
                printf("0");
            else
                printf("1");
        }
    }
    return 0;
}

F.Painting Fence

在这里插入图片描述

题意

横着或者竖着把栅栏刷完

思路

最多刷n次就可以刷完,所以答案一定小于等于n,一开始我想二分,后面发现可以暴力过。对于每一段比较横着刷和竖着刷的最小值,递归求解。

#include<iostream>
using namespace std;
const int N = 5e3 + 233;
int a[N];
int dfs(int l, int r, int u)
{
    if(l > r)
        return 0;
    int h = a[l], idx = l;
    for(int i = l; i <= r; i++)
        h = a[i] < h ? a[idx = i] : h;
    return min(r - l + 1, dfs(l, idx - 1, h) + h - u + dfs(idx + 1, r, h));
}
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++)
        cin >> a[i];
    cout << dfs(1, n, 0) << endl;
}

G.数对

在这里插入图片描述

题意

找到满足clcm(a,b)-dgcd(a,b)=x;的情况种数。

思路

在这里插入图片描述

#include<iostream>
using namespace std;
const int N=2e7+10;
typedef long long ll;
int prime[N],dp[N],cnt,n,c,d,x;
bool isPrime[N];
ll ans=0;
void init(){
	int n=2e7;cnt=0;
	for(int i=2;i<=n;i++)
    {
		if(isPrime[i]==0)
        {
			prime[++cnt]=i;
			dp[i]=1;
		}
		for(int j=1;j<=cnt && 1ll*prime[j]*i<=n;j++)
        {
            isPrime[i * prime[j]] = 1;
            if(i%prime[j]==0 )
                dp[i * prime[j]] = dp[i];
            else
                dp[i * prime[j]] = dp[i] + dp[prime[j]];
            if(i%prime[j]==0)
                break;
        }
	}
}

int main()
{
	init();
    scanf("%d", &n);

    while(n--)
    {
        scanf("%d%d%d", &c, &d, &x);
        ans=0;
		for(int i=1;i*i<=x;i++)
        {
			if(x%i!=0)
                continue;
            ll k1 = (x / i) + d;
            if(k1%c==0)
                ans += (1ll << dp[k1 / c]);
            if(i*i==x)
                continue;
            ll k2 = i + d;
            if(k2%c==0)
                ans += (1ll << dp[k2 / c]);
        }
        cout << ans << endl;
    }
	return 0;
}

标签:周赛,训练,vis,int,else,++,printf,include,swpu
来源: https://blog.csdn.net/qq_53288014/article/details/115679077

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有