(CF792 ABCD题解) 模拟,树状数组

A题目链接:http://codeforces.com/problemset/problem/792/A

//
题意: 给你n个数,问你两个数直接的差值得绝对值最小为多少,及有多少对满足这样的数/

分析:
排序后直接扫一遍即可


//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

const int maxn = 200010;
int a[maxn];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    sort(a,a+n);
    int mindis = 2000000010;
    int pairs = 0;
    for(int i=0;i<n-1;i++)
    {
        int t = abs(a[i+1]-a[i]);
        if(t < mindis)
        {
            mindis = t;
            pairs = 1;
        }
        else if(t == mindis) pairs++;
    }
    printf("%d %d\n",mindis,pairs);
    return 0;
}

B题目链接:http://codeforces.com/problemset/problem/792/B

//
题意: 有n个人顺时针围成一圈,编号从1~n,刚开始时第一个人为leader,现在进行k轮游戏
每一轮有一个数ai,表示从leader的后一个人开始往后数ai个人,将最后一个人出圈,并且将出圈人的后一个人设为下一轮的leader
问你每一轮出圈人的编号?

分析:
由于n很小,所以我们可以直接进行模拟即可,将圈直接看成一行,编号1~n
在每一轮中有:
leader :标记leader为从头开始的第几个人
n: 还剩下的人数
所以下一个出圈的人为第 (leader + a[i]) % n 个人
再将后面的编号往前移动一位即可
依次模拟下去

**注意对边界情况的处理**
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

const int maxn = 110;
int ch[maxn];
int a[maxn];
int ans[maxn];

int main()
{
    int n,k;
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++) ch[i] = i;
    for(int i=1;i<=k;i++) scanf("%d",&a[i]);
    int leader = 1;
    for(int i=1;i<=k;i++)
    {
        int t = (leader + a[i]) % n;
        if(t == 0) t = n;
        ans[i] = ch[t];
        for(int j = t+1;j<=n;j++) ch[j-1] = ch[j];
        if(t == n) leader = 1;
        else leader = t;
        n--;
    }
    for(int i=1;i<=k;i++)
    {
        if(i == 1) printf("%d",ans[i]);
        else printf(" %d",ans[i]);
    }
    printf("\n");
    return 0;
}

C题目链接:http://codeforces.com/problemset/problem/792/C

//
**代码是WA的,今后找机会改**
题意: 给你一个长度最大为100000的正整数,为你最少删去多少个数使得他是3的倍数(没有前导0)

分析:一个数的所有位数之和是3的倍数那么那个数就是3的倍数
我们也可以将每一位看成0,1,2,3
所以这个数 %3 后只有可能有3中情况:0,1,2、
若余数为0:可以直接输出
若余数为1:去掉一个1或两个2 (有很多关于0的情况的讨论)
若余数为2:去掉一个2或两个1
分情况讨论即可
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

const int maxn = 100010;
char s[maxn];

int main()
{
    freopen("input.txt","r",stdin);
    while(scanf("%s",s)!=EOF)
    {
        int len = strlen(s);
        int sum = 0;
        int num0 = 0;
        int num1 = 0;
        int num2 = 0;
        for(int i=0;i<len;i++)
        {
            sum += s[i] - '0';
            if(s[i]-'0' == 0) num0++;
            else if((s[i]-'0') % 3 == 1) num1++;
            else if((s[i]-'0') % 3 == 2) num2++;
        }
        int t = sum % 3;
        if(t == 0) printf("%s\n",s);
        else if(t == 1)
        {
            if(num1 == 0)
            {
                if(num2 <2) printf("-1\n");
                else if(num2 ==2)
                {
                    if(len == 2) printf("-1\n");
                    else
                    {
                        int k = 0;
                        while(s[k] == '0' || (s[k]-'0')%3 == 2) k++;
                        if(k >= len) printf("0\n");
                        else
                        {
                            for(int i=k;i<len;i++) if((s[i]-'0')%3 != 2)
                            printf("%c",s[i]);
                            printf("\n");
                        }
                    }
                }
            }
            else if(num1 > 1)
            {
                printf("%c",s[0]);
                int num = 1;
                for(int i=1;i<len;i++)
                {
                    if(num == 1 && (s[i]-'0') == 1) num--;
                    else  printf("%c",s[i]);
                }
                printf("\n");
            }
            else if(num1 == 1)
            {
                if((s[0]-'0')%3 != 1)
                {
                    printf("%c",s[0]);
                    int num = 1;
                    for(int i=1;i<len;i++)
                    {
                        if(num == 1 && (s[i]-'0')%3 == 1) num--;
                        else  printf("%c",s[i]);
                    }
                    printf("\n");
                }
                else
                {
                    if(num2 < 2)
                    {
                        int k=1;
                        while(s[k]=='0') k++;
                        if(k >= len) k = len-1;
                        for(int i=k;i<len;i++) printf("%c",s[i]);
                        printf("\n");
                    }
                    else
                    {
                        if(s[1]!='0')
                        {
                            for(int i=1;i<len;i++) printf("%c",s[i]);
                            printf("\n");
                        }
                        else if(s[2] != '0')
                        {
                            for(int i=2;i<len;i++) printf("%c",s[i]);
                            printf("\n");
                        }
                        else
                        {
                            int num = 2;
                            printf("%c%c%c",s[0],s[1],s[2]);
                            for(int i=3;i<len;i++)
                            {
                                if(num > 0 && (s[i]-'0')%3 == 2) num--;
                                else printf("%c",s[i]);
                            }
                            printf("\n");
                        }
                    }
                }
            }
        }
        else if(t == 2)
        {
            if(num2 == 0)
            {
                if(num1 <2) printf("-1\n");
                else if(num1 ==2)
                {
                    if(len == 2) printf("-1\n");
                    else
                    {
                        int k = 0;
                        while(s[k] == '0' || (s[k]-'0')%3 == 1) k++;
                        if(k >= len) printf("0\n");
                        else
                        {
                            for(int i=k;i<len;i++) if((s[i]-'0')%3 != 1)
                            printf("%c",s[i]);
                            printf("\n");
                        }
                    }
                }
            }
            if(num2 > 1)
            {
                printf("%c",s[0]);
                int num = 1;
                for(int i=1;i<len;i++)
                {
                    if(num == 1 && (s[i]-'0')%3 == 2) num--;
                    else  printf("%c",s[i]);
                }
                printf("\n");
            }
            if(num2 == 1)
            {
                if((s[0]-'0')%3 != 2)
                {
                    printf("%c",s[0]);
                    int num = 1;
                    for(int i=1;i<len;i++)
                    {
                        if(num == 1 && (s[i]-'0')%3 == 2) num--;
                        else  printf("%c",s[i]);
                    }
                    printf("\n");
                }
                else
                {
                    if(num1 < 2)
                    {
                        int k=1;
                        while(s[k]=='0') k++;
                        if(k >= len) k = len-1;
                        for(int i=k;i<len;i++) printf("%c",s[i]);
                        printf("\n");
                    }
                    else
                    {
                        if(s[1]!='0')
                        {
                            for(int i=1;i<len;i++) printf("%c",s[i]);
                            printf("\n");
                        }
                        else if(s[2] != '0')
                        {
                            for(int i=2;i<len;i++) printf("%c",s[i]);
                            printf("\n");
                        }
                        else
                        {
                            int num = 2;
                            printf("%c%c%c",s[0],s[1],s[2]);
                            for(int i=3;i<len;i++)
                            {
                                if(num > 0 && (s[i]-'0')%3 == 1) num--;
                                else printf("%c",s[i]);
                            }
                            printf("\n");
                        }
                    }
                }
            }
        }
    }
    return 0;
}

D题目链接:http://codeforces.com/problemset/problem/792/D

//
题意:给你一颗完全二叉树,标号规则如图所示(先序序列),
现在从一个节点出发,可以进行U:向上,R:向右,L:向左 移动这三种操作 (当不能移动时不动)
经过s操作后,问你最后到达哪一节点?

分析:
满二叉树的标号方式和我们所学的树状数组一样,所以我们想到了树状数组
设当前所在节点的编号为u,那么pos = u&-u : 表示和u处在层的第一个节点的编号
若 u&(2*pos) != 0 表示 u 节点在父节点的右侧
若 u&(2*pos) == 0 表示 u 节点在父节点的左侧
并且我们发现从最后一层开始相邻两层之间的节点的编号差值从1 开始成倍增长
所以我们根据以上信息模拟即可
//


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

long long n,q,u,root;
string s;

int main()
{
    scanf("%I64d %I64d",&n,&q);
    root = (n + 1) / 2;
    for(int i=0;i<q;i++)
    {
        cin>>u>>s;
        int len = s.length();
        for(int j=0;j<len;j++)
        {
            long long pos = u&-u;
            if(s[j] == 'U' && u != root)
            {
                if(u&(2*pos)) u -= pos;
                else u += pos;
            }
            else if(s[j] == 'L')
            {
                pos /= 2;
                u -= pos;
            }
            else if(s[j] == 'R')
            {
                pos /= 2;
                u += pos;
            }
        }
        printf("%I64d\n",u);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值