首页 > 代码库 > poj 3484 Showstopper

poj 3484 Showstopper

                                                                                                                                                           Showstopper
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2057   Accepted: 612

Description

Data-mining huge data sets can be a painful and long lasting process if we are not aware of tiny patterns existing within those data sets.

One reputable company has recently discovered a tiny bug in their hardware video processing solution and they are trying to create software workaround. To achieve maximum performance they use their chips in pairs and all data objects in memory should have even number of references. Under certain circumstances this rule became violated and exactly one data object is referred by odd number of references. They are ready to launch product and this is the only showstopper they have. They need YOU to help them resolve this critical issue in most efficient way.

Can you help them?

Input

Input file consists from multiple data sets separated by one or more empty lines.

Each data set represents a sequence of 32-bit (positive) integers (references) which are stored in compressed way.

Each line of input set consists from three single space separated 32-bit (positive) integers X Y Z and they represent following sequence of references: X, X+Z, X+2*Z, X+3*Z, …, X+K*Z, …(while (X+K*Z)<=Y).

Your task is to data-mine input data and for each set determine weather data were corrupted, which reference is occurring odd number of times, and count that reference.

Output

For each input data set you should print to standard output new line of text with either “no corruption” (low case) or two integers separated by single space (first one is reference that occurs odd number of times and second one is count of that reference).

Sample Input

1 10 1
2 10 1

1 10 1
1 10 1

1 10 1
4 4 1
1 5 1
6 10 1

Sample Output

1 1
no corruption
4 3

题意:题目给出了多个等差数列的首项X_i,末项Y_i和公差Z_i,我们现在可以想象成把这些等差数列里的所有不同的数组成一个集合S,需要寻找集合S里的一个元素,这个元素在所有这些等差数列中总共出现过奇数次(题意知除该元素外其余的元素都出现偶数次)。
思路:假若将集合S中的元素从小到大排列,用time[i]表示第i个元素在等差数列中出现的次数,再设元素j出现了奇数次,那么在元素j出现前, ∑time[i](0<=i<j)一定是偶数,若此时再加上time[j],和必定变为奇数,对此可用二分查找的方式找到元素j,而实际
∑time[i](0<=i<j)时,并不用知道具体每个元素出现多少次,只需要计算每个数列中比元素j小的元素的数量并累加求和即可。
还有这题的输入很奇特,要注意!!!
AC代码:
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<sstream>
using namespace std;
const int N_MAX = 1000000+4;
typedef long long ll;
ll X[N_MAX], Y[N_MAX], Z[N_MAX];
ll num[N_MAX];//记录每个数列有几个数
int N;
char buf[1024];

ll C(const ll&x){//为了判断x出现次数是否奇数次,首先判断小于等于x的数总共是多少,如果是奇数,说明x可能太大,若全是偶数,则x一定太小
    ll sum = 0;
    for (int i = 0; i < N; i++) {
        if (Y[i] <= x)sum += num[i];
        else if (X[i] <= x)sum += (x - X[i]) / Z[i] + 1;
    }
    return sum;
}
bool input() {
    N = 0;
    bool what=0;
    while ((what=(gets_s(buf)!=NULL))&&strlen(buf)>2) {//主要是为了处理回车的操作
        sscanf(buf,"%lld%lld%lld",&X[N],&Y[N],&Z[N]);
        N++;
    }
    return what || N;//如果没有输入了并且N也为0,那么说明没有需要操作的数据了
}

int main() {
    while (input()) {
        if (!N)continue;//只输入空格就无视这种情况
        ll judge = 0;
        for (int i = 0; i < N;i++) {
            num[i] = (Y[i] - X[i]) / Z[i] + 1;
            judge += num[i];
        }
        if (!(judge & 1)) {//若所有的数的数量加起来为偶数,意味着没有异常元素
            printf("no corruption\n");
        }
        else {
            ll lb = 0,ub=INT_MAX;
            while (ub-lb>1) {
                ll mid = (lb+ub) >> 1;
                if (!(C(mid) & 1))lb = mid;
                else ub = mid;/////(lb,ub]
            }
            printf("%lld %lld\n",ub,C(ub)-C(ub-1));
        }
    }
    return 0;
}

 

 


poj 3484 Showstopper