1. 程式人生 > >CH0805 前綴和維護奇偶 二分答案

CH0805 前綴和維護奇偶 二分答案

pac check HERE ret 數量 getch c++ 由於 文件的

題面

描述

lsp 學習數學競賽的時候受盡了同仁們的鄙視,終於有一天......受盡屈辱的 lsp 黑化成為了黑暗英雄Lord lsp。就如同中二漫畫的情節一樣,Lord lsp 打算毀掉這個世界。數學競賽界的精英 lqr 打算阻止Lord lsp 的陰謀,於是
她集合了一支由數學 競賽選手組成的超級行動隊。由於隊員們個個都智商超群,很快,行動隊便來到了 Lord lsp 的黑暗城堡的下方。

但是,同樣強大的 Lord lsp 在城堡周圍布置了一條“不可越過”的堅固防線。防線由很 多防具組成,這些防具分成了 N 組。我們可以認為防線是一維的,那麽每一組防具都分布 在防線的某一段上,並且同一組防具是等距離排列的。也就是說,我們可以用三個整數 S, E 和 D 來描述一組防具,即這一組防具布置在防線的 S,S + D,S + 2D,...,S + KD(K∈ Z,S + KD≤E,S + (K + 1)D>E)位置上。

黑化的 Lord lsp 設計的防線極其精良。如果防線的某個位置有偶數個防具,那麽這個位 置就是毫無破綻的(包括這個位置一個防具也沒有的情況,因為 0 也是偶數)。只有有奇數 個防具的位置有破綻,但是整條防線上也最多只有一個位置有奇數個防具。作為行動隊的隊 長,lqr 要找到防線的破綻以策劃下一步的行動。但是,由於防具的數量太多,她實在是不 能看出哪裏有破綻。作為 lqr 可以信任的學弟學妹們,你們要幫助她解決這個問題。
輸入格式

輸入文件的第一行是一個整數 T,表示有 T 組互相獨立的測試數據。 每組數據的第一行是一個整數 N。
之後 N 行,每行三個整數 Si,Ei,Di,代表第 i 組防具的三個參數。

輸出格式

對於每組測試數據,如果防線沒有破綻,即所有的位置都有偶數個防具,輸出一行 “There‘s no weakness.”(不包含引號)

否則在一行內輸出兩個空格分隔的整數 P 和 C,表示在位置 P 有 C 個防具。當然 C 應 該是一個奇數。
樣例輸入

3
2
1 10 1
2 10 1
2
1 10 1
1 10 1
4
1 10 1
4 4 1
1 5 1
6 10 1

樣例輸出

1 1
There‘s no weakness.
4 3

數據範圍與約定
對於 30% 的數據,滿足防具總數不多於 107。
對於 100% 的數據,滿足防具總數不多於 108,Si≤Ei,1≤T≤5,N≤200000,0≤Si, Ei,Di≤231-1。

解法

因為為只有一個奇數,所以可以前綴和維護,設奇數位置為p,則p以前的前綴和為偶,p以後的前綴和為奇。

代碼

#include<bits/stdc++.h>

using namespace std;
const int N=200005;

struct node { int s,e,d; } a[N];
int n;

int read()
{
    int x=0,p=1; char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') p=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*p;
}

bool check(int mid)
{
    int sum=0;
    for(int i=1;i<=n;i++)
        if(mid>=a[i].s) sum+=1+(min(a[i].e,mid)-a[i].s)/a[i].d;
    return sum&1;
}

int main()
{
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    int T=read(),l,r,ans;
    while(T--)
    {
        n=read(); l=0x7fffffff,r=-1;
        for(int i=1;i<=n;i++)
        {
            a[i].s=read(),a[i].e=read(),a[i].d=read();
            l=min(a[i].s,l),r=max(a[i].e,r);
        }

        int ok=0,sum=0;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(check(mid))
                ans=mid,r=mid-1,ok=1;
            else l=mid+1;
        }

        if(ok)
        {
            for(int i=1;i<=n;i++)
                if(ans>=a[i].s && ans<=a[i].e && (ans-a[i].s)%a[i].d==0 ) sum++;
            printf("%d %d\n",ans,sum);
        }
        else printf("There's no weakness.\n");
    }
    return 0;
}

CH0805 前綴和維護奇偶 二分答案