HDU 6205 card card card ( 思维 )

题意 : 给定两个序列 a 和 b ,保证 a 数列的和 == b数列的和,从头到尾考虑 (a[i] - b[i]) 的前缀和,直到前缀和为负数则无法进行下去,所得的便是a[1~i]的和,现在有一个操作,就是你可以将最前面的a[1] && b[1] 这两个数放到末尾去,问你最少经过多少次这样的操作能够使得去到的a[1~i]的的和是最大的

分析 : 发现因为有 a数列的和 == b数列的和,所以肯定有以某一个数开头使得将所有序列的数全部取完即 sum( a[1~末尾] ),我们先构造出 sub[i] = a[i] - b[i] 的序列,然后每一次选取一个正的sub[i] 作为开头来判断是否可行,如果在 i~k-1都可行,但是加上sub[k]就变得不可行,那么下一个开头就不是离 sub[i] 右边最近的一个正整数作为头,而是离 sub[k] 右边(当然最后一个元素的右边是第一个元素) 最近的一个正整数作为开头,为什么这样做呢?首先先如果按照第一种做法肯定是正确的,但是在时间上不是最优的,因为从 i~(k-1) 都是可行的,那么如果下一个开头的数还是在 i~(k-1) 这个序列里面考虑的话,那么下一次还是会在 k 这里停止,因为 sub[i] 是正数,细想就可以想明白了。模拟这个操作可以将数组复制一边粘到原数组末尾,但是这里我用了%操作,其实都一样。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
int n, a[maxn], b, sub[maxn];
inline int Scan()
{
    int res = 0, ch;
    bool flag = false;
    if((ch=getchar()) == ‘-‘) flag = true;
    else if(ch>=‘0‘ && ch<=‘9‘) res = ch-‘0‘;
    while((ch=getchar())>=‘0‘ && ch<=‘9‘) res = res*10+ch-‘0‘;
    return flag?-res:res;
}
int main(void)
{
    while(~scanf("%d", &n)){
        for(int i=0; i<n; i++) a[i] = Scan();
        int negative = 0;
        for(int i=0; i<n; i++){
            b = Scan();
            sub[i] = a[i] - b;
            if(sub[i] < 0) negative++;
        }
        if(negative == n) { puts("0"); continue; }///全都是负数的情况
        int sum = 0, pos = 0;
        while(true){
            bool ok = true;
            while(sub[pos] < 0) pos++;///从当前位置开始找到右边第一个正数
            for(int i=pos, j=0; !(j!=0&&i==pos); j++, i=(i+1)%n){///开始累加前缀和sum,j的作用是辅助判断i是否已经第二次到达了pos这个位置,也就是pos是满足题意的!
                sum += sub[i];///累加前缀和
                if(sum < 0){///如果小于0,则在这里停止
                    ok = false;
                    pos = i;///记录一下当前位置
                    sum = 0;///重置前缀和
                    break;
                }
            }
            if(ok) break;
        }
        printf("%d\n", pos);
    }
    return 0;
}

瞎 : 沈阳网络赛的题,靠队友带飞,学习队友代码orz

时间: 2024-10-10 04:24:13

HDU 6205 card card card ( 思维 )的相关文章

HDU 6154 CaoHaha&#39;s staff 思维 找规律

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6154 题目描述: 围成一个面积不小于S的多边形, 最少需要多少根儿线段, 线段可以为单元格边或者对角线 解题思路: 最大的面积肯定是由根号2为边长的正方形围成了, 那么我们把所有正方形都遍历一遍, 找出S介于N, N+1的那个上界N+1设为max, 因为MAX所围成的多边形面积和MAX-1, MAX-2, MAX-3围成的多边形面积, 找出满足条件的最小的一个即可 代码: #include <io

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha&#39;s staff 思维

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6154 题意:在笛卡尔坐标系下,画一个面积至少为  n 的简单多边形,每次只能画一条边或者一个格子的对角线,问至少要画几条. 解法:如果一个斜着的矩形长宽分别是 a,b,那么它的面积是 2ab.最优解肯定是离 sqrt(n/2)很近的位置.想想 n=5 时答案为什么是7 然后在那个小范围内枚举一下就好了.我给一张做题时画的图 #include <bits/stdc++.h> using namesp

hdu 4710 Balls Rearrangement (数学思维)

题意:就是  把编号从0-n的小球对应放进i%a编号的盒子里,然后又买了新盒子, 现在总共有b个盒子,Bob想把球装进i%b编号的盒子里.求重置的最小花费. 每次移动的花费为y - x ,即移动前后盒子编号的差值的绝对值. 算法: 题目就是要求                  先判断  n与  lcm(a,b)的大小,每一个周期存在循环,这样把区间缩短避免重复计算. 如果n>lcm(a,b)则   ans = (n/lcm)*solve(lcm)+solve(n%lcm) 否则   ans =

HDU 3972 1 M possible(思维)

1 M possible Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 2048/1024 K (Java/Others) Total Submission(s): 1031    Accepted Submission(s): 343 Problem Description There are 3*N+2 nonnegative integers. Except two special integers, the rest 3

hdu 6205 card card card 尺取+超神读入挂

题没啥好说的 我就是想把读入挂记录一下 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug(a) cerr<<#a<<"=="<<a<<endl 4 using namespace std; 5 typedef long long ll; 6 typedef pair<int,int> pii; 7 8

hdu 6205: card card card【输入挂】

题目链接 感谢 http://blog.csdn.net/txgang/article/details/77568491 #include<bits/stdc++.h> using namespace std; namespace FastIO { const static int MX=1e6; bool IOerror=0; char nc() { static char buf[MX],*p1=buf+MX,*pend=buf+MX; if(p1==pend) { p1=buf; pen

AtCoder Beginner Contest 053 D - Card Eater(思维)

Problem Statement Snuke has decided to play a game using cards. He has a deck consisting of NN cards. On the ii -th card from the top, an integer AiAi is written. He will perform the operation described below zero or more times, so that the values wr

POJ 2062 HDU 1528 ZOJ 2223 Card Game Cheater

水题,感觉和田忌赛马差不多 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; struct P1 { int Num; int Hua; } Play1[30]; struct P2 { int Num; int Hua; } Play2[30]; bool cmp1(const P1&a,const P1&b

HDU 6205 2017沈阳网络赛 思维题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6205 题意:给你n堆牌,原本每一堆的所有牌(a[i]张)默认向下,每次从第一堆开始,将固定个数的牌(b[i]张)翻上,然后下一堆继续,直到没有足够的牌翻上,然后你可以获得当前已经操作过的堆的所有牌.最初你可以调整堆的顺序,把第一堆放到最后一堆(逆时针旋转),你可以重复这个操作,问你要重复多少次这个操作,才能获得最多的牌. 解法:先把这个序列复制一遍放在原来的序列后面.当i=n的时候结束就可以了,每次