[BestCoder] Round #3

1001

http://acm.hdu.edu.cn/showproblem.php?pid=4907

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
using namespace std;
const int maxn=200005;
bool vis[maxn];
int f[maxn];//第i时间得到的额外任务要在f[i]时间被执行,主要就是从当前任务向后找直到找到空闲时间为止,
int n,m;
int q;

int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        memset(vis,0,sizeof(vis));
        int t;
        while(n--)
        {
            scanf("%d",&t);
            vis[t]=1;
        }
        for(int i=maxn-1;i>=1;i--)
        {
            if(!vis[i])
                f[i]=i;
            else
                f[i]=f[i+1];
        }
        while(m--)
        {
            scanf("%d",&q);
            printf("%d\n",f[q]);
        }
    }
    return 0;
}

1002

http://acm.hdu.edu.cn/showproblem.php?pid=4908

题意为 给定一个1 -N的排列,再给定一个数M(1<=M<=N),问有多少连续的长度为奇数子序列,使得M在其中为中位数(M在子序列中)。

比如样例

5 3

4 5 3 2 1 N=5, M=3

{3},{5,3,2},{4,5,3,2,1} 为符合题意的连续子序列....

当时做的时候把包含M的所有长度为0,1,2.......的连续子序列都枚举了出来,然后判断判断M是否是中位数,结果 果断超时.......

贴一下题解思路:

写了一堆字,CSDN的排版太....了,贴图片把.

代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
using namespace std;
const int maxn=40002;
int sum[maxn];//从1到第i个数的和是多少
int d[maxn*2+1];//记录状态
int n,m;

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        sum[0]=0;
        int pos;//m的位置
        memset(d,0,sizeof(d));
        int a;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            if(a==m)
                pos=i;
            if(a<m)
                sum[i]=sum[i-1]-1;
            else if(a>m)
                sum[i]=sum[i-1]+1;
            else
                sum[i]=sum[i-1];
        }
        for(int i=0;i<pos;i++)
        {
            d[sum[i]+maxn]++;//前面的状态
           // cout<<"sss"<<d[sum[i]+maxn]<<endl;
        }
        int ans=0;
        for(int i=pos;i<=n;i++)
        {
            ans+=d[sum[i]+maxn];
        }

        printf("%d\n",ans);

    }
    return 0;
}

1003

http://acm.hdu.edu.cn/showproblem.php?pid=4909

解题思路:

题意为给定一个包含小写字母的序列,其中可能有一个‘?‘,也可能没有,有的话最多只有一个,‘?‘可以删除,也可以替换为任意一个小写字母,问给定的序列中有多少个连续的子序列,保证所有小写字母出现的次数为偶数。

用一个26位二进制数来表示状态,每一位代表一个小写字母,关键是:

当一个状态出现时,后面又加上几个连续的字母,(状态的改变用状态的某一位异或1,)该状态又一次出现了,那么加上的那几个连续字母是符合题意的一个串,只有异或偶数倍某一位的状态才能回到本身, 比如一开始某一位的状态为0,异或一次0^1=1,  1^1=0......  再比如是1,  1^1=0,0^1=1

要求记录每个状态出现的次数,那么26位,状态有 2^26-1个,用map<int,int>hash来模拟数组

hash[x] ,代表状态x出现的次数

对于有出现’?‘的串,可以分为三部分,?之前部分符合题意的串,之后部分符合题意的串,加上?以后符合题意的串,具体思路在代码注释中。

参考:http://blog.csdn.net/accelerator_/article/details/38363245#comments  大哭由于作者文章没有注释,代码看了好半天,才慢慢弄懂。。。。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <map>
using namespace std;
const int maxn=20010;
char str[maxn];
int cas,n,p,x;
int ans;
map<int,int>hash;//hash[x]表示状态x出现了多少次

int main()
{
    scanf("%d",&cas);
    while(cas--)
    {
        hash.clear();
        scanf("%s",str);
        p=-1;
        n=strlen(str);
        for(int i=0;i<n;i++)
        {
            if(str[i]=='?')
            {
                p=i;
                break;
            }
        }
        ans=0;

        if(p==-1)//一个状态出现过,后面又加了几个字母,而这个状态又重新出现了,说明后面加的
        {        //每个字母都是偶数个,因为0^1=1,1^1=0
            x=0;
            hash[0]++;
            for(int i=0;i<n;i++)
            {
                x^=(1<<(str[i]-'a'));
                ans+=hash[x];//前面出现过hash[x]次,加上它
                hash[x]++;
            }
            printf("%d\n",ans);
            continue;
        }
        else
        {
            x=0;//计算'?'前面的串符合题意的有多少个
            hash[0]++;
            for(int i=0;i<p;i++)
            {
                x^=(1<<(str[i]-'a'));
                ans+=hash[x];
                hash[x]++;
            }
            hash.clear();//注意此时清空,后面的串是独立计算的

            x=0;//计算'?'后面的串符合题意的有多少个
            hash[0]++;
            for(int i=p+1;i<n;i++)
            {
                x^=(1<<(str[i]-'a'));
                ans+=hash[x];
                hash[x]++;
            }

            x=0;
            if(hash.count(x))
                ans+=hash[x];
            //花了N长时间终于明白上面这句话什么意思了
            //把?看做空串(也可以理解为删除)和后面的串一块,有多少符合题意的,这时候状态是0

            for(int i=0;i<26;i++)//枚举?的值与后面的串一块,有多少符合题意的
            {
                if(hash.count(x^(1<<i)))
                    ans+=hash[x^(1<<i)];
            }

            for(int i=p-1;i>=0;i--)//处理前部分时,和?以及后半部分建立了联系,注意一定是逆向,不能是正向,
            {
                x^=(1<<(str[i]-'a'));
                if(hash.count(x))//寻找后半部分出现相同的状态,此时?为空, 这也是要逆向的原因
                    ans+=hash[x];

                for(int j=0;j<26;j++)//枚举?的值
                {
                    if(hash.count(x^(1<<j)))
                        ans+=hash[x^(1<<j)];
                }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
时间: 2024-10-13 03:26:27

[BestCoder] Round #3的相关文章

BestCoder Round #91

传送门:http://acm.hdu.edu.cn/search.php?field=problem&key=BestCoder+Round+%2391&source=1&searchmode=source A题:给你n种字母,每种字母有个权值vali,共cnti个,现在让你在里面挑出任意数量的字符,组合成一个字符串,该字符串的权值的计算方式为val1*1+val2*2+--+valn*n,让你输出字符串最大的权值是多少.这题很容易会有一个错误的贪心,就是把val为负的舍去,然后v

BestCoder Round #65 (ZYB&#39;s Game)

ZYB's Game Accepts: 672 Submissions: 1207 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description ZYBZYBZYB played a game named NumberBombNumber BombNumberBomb with his classmates in hiking:a host keeps a

hdu5418 BestCoder Round #52 (div.2) Victor and World ( floyd+状压dp)

Problem Description After trying hard for many years, Victor has finally received a pilot license. To have a celebration, he intends to buy himself an airplane and fly around the world. There are n countries on the earth, which are numbered from 1 to

hdu 5163 Taking Bus (BestCoder Round #27)

Taking Bus                                                               Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 501    Accepted Submission(s): 203 Problem Description Bestland has a v

BestCoder Round #11 (Div. 2) 前三题题解

题目链接: huangjing hdu5054 Alice and Bob 思路: 就是(x,y)在两个參考系中的表示演全然一样.那么仅仅可能在这个矩形的中点.. 题目: Alice and Bob Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 216    Accepted Submission(s): 166 Problem De

BestCoder Round #16

BestCoder Round #16 题目链接 这场挫掉了,3挂2,都是很sb的错误 23333 QAQ A:每个数字,左边个数乘上右边个数,就是可以组成的区间个数,然后乘的过程注意取模不然会爆掉 B:dp,dp[i][2]记录下第一长的LIS,和第二长的LIS,哎,转移的时候一个地方写挫掉了导致悲剧啊QAQ C:首先如果知道Nim游戏的,就很容易转化问题为,一些数字是否能选几个能否异或和为0,那么就是每个数字拆成40位,然后每一位异或和为0,这样就可以构造出40个方程,然后高斯消元求解,如果

BestCoder Round #11 (Div. 2) 题解

HDOJ5054 Alice and Bob Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 302    Accepted Submission(s): 229 Problem Description Bob and Alice got separated in the Square, they agreed that if they

BestCoder Round #9

BestCoder Round #9 题目链接 A:暴力枚举一个数字,就能求出另一个数字,for一遍即可 B:博弈,判断前n - 1个开头连续1的奇偶性即可 C:先预处理出每个点对应哪几个点,每次查询计算一次即可 代码: A: #include <cstdio> #include <cstring> #include <vector> #include <set> #include <algorithm> #include <cmath&g

hdu 4956 Poor Hanamichi BestCoder Round #5(数学题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4956 Poor Hanamichi Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7    Accepted Submission(s): 4 Problem Description Hanamichi is taking part in

BestCoder Round #4 前两题 hdu 4931 4932

第一题太水了.. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int a[6]; 7 int main(){ 8 int cas; 9 scanf( "%d", &cas ); 10 while( cas-- ){ 11 for( int i = 0; i <