• hdu 4678


    HDU 4768: Flyer

    题意:

    有N个社团,每个社团三个属性A,B,C,表示会向编号A+k*C的同学发传单(k=0,1,2...  && A+k*C <= B)。题目保证最多有一个人收到的传单数是奇数。求如果有人收到传单是奇数,输出编号和他收到的传单数。

    思路:

    观察最后情况,可以发现,要么每个人都是偶数。要么有一个是奇数。观察其前缀和,发现奇数那个人之前的前缀和都是偶数,之后都是奇数。所以,二分之。

    代码:

    (上交大牛代码……)

    复制代码
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int n, a[100001][3];
    long long sum;
    
    bool check(int now){
        long long sum = 0;
        for (int i = 1; i <= n; i++)
            if (now >= a[i][0])
            {
                int Right = min(a[i][1], now);
                if (a[i][2]) sum += (long long)(Right - a[i][0]) / a[i][2] + 1;
                else sum++;
            }
        return(sum & 1);
    }
    
    int read(){
        char ch;
        for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar());
        int cnt = 0;
        for (; ch >= '0' && ch <= '9'; ch = getchar()) cnt = cnt * 10 + ch - '0';
        return(cnt);
    }
    
    
    int main(){
        //freopen("j.in", "r", stdin);
        //freopen("j.out", "w", stdout);
        for (;;)
        {
            if (scanf("%d", &n) != 1) return 0;
            sum = 0;
            int Max = 0;
            for (int i = 1; i <= n; i++) 
            {
                a[i][0] = read(); a[i][1] = read(); a[i][2] = read();
                if (a[i][2]) sum += (long long)(a[i][1] - a[i][0]) / a[i][2] + 1;
                else sum++;
                Max = max(Max, a[i][1]);
            }
            if (!(sum & 1))
            {
                printf("DC Qiang is unhappy.
    ");
                continue;
            }
            long long Left = 0, Right = Max, Mid = (Left + Right) >> 1;
            while (Left + 1 < Right)
            {
                if (check(Mid)) Right = Mid;
                else Left = Mid;
                Mid = (Left + Right) >> 1;
            }
            printf("%d", Right);
            int cnt = 0;
            for (int i = 1; i <= n; i++)
                if (Right >= a[i][0] && Right <= a[i][1] && !((Right - a[i][0]) % a[i][2])) ++cnt;
            printf(" %d
    ", cnt);
        }
    }  
    复制代码
  • 相关阅读:
    Gym102501G Swapping Places(拓扑排序)
    2019SWERC题解
    CF364D Ghd(随机化)
    CF500E New Year Domino(并查集+栈)
    CF280C Game on Tree(期望)
    CF1093G Multidimensional Queries(线段树)
    CF677D Vanya and Treasure(最短路)
    CF788C The Great Mixing(最短路)
    queryset高级用法:prefetch_related
    queryset高级用法:select_related
  • 原文地址:https://www.cnblogs.com/unknownname/p/7903575.html
Copyright © 2020-2023  润新知