Description
给你n个数列,问哪一个数字在所有的数列中出现了奇数次(最多一个)。
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
Analysis
我们假装按大小排好了每个数,然后我们发现,如果统计每个数出现的次数,要求的数X是奇数,其他的是偶数,那么记录前缀和,X之前全为偶数(偶+偶+...+偶=偶),X及X以后都是奇数(奇+偶=奇),那我们就可以按照这个规律二分了。
这道题还是蛮有意思的,如果奇数和偶数对掉的话,这道题就不可做了。
Code
1 #include<set> 2 #include<map> 3 #include<queue> 4 #include<stack> 5 #include<cmath> 6 #include<cstdio> 7 #include<cstring> 8 #include<iostream> 9 #include<algorithm> 10 #define RG register int 11 #define rep(i,a,b) for(RG i=a;i<=b;++i) 12 #define per(i,a,b) for(RG i=a;i>=b;--i) 13 #define ll long long 14 #define inf 0x8f8f8f8f8f 15 #define maxn 100005 16 using namespace std; 17 ll X[maxn],Y[maxn],Z[maxn],cnt; 18 char s[maxn]; 19 inline int read() 20 { 21 int x=0,f=1;char c=getchar(); 22 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 23 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 24 return x*f; 25 } 26 27 int judge(ll lim) 28 { 29 ll sum=0; 30 rep(i,1,cnt) 31 { 32 if(lim<X[i]) continue; 33 sum+=(min(Y[i],lim)-X[i])/Z[i]+1; 34 } 35 return sum&1; 36 } 37 38 ll cal(ll lim) 39 { 40 ll sum=0; 41 rep(i,1,cnt) 42 { 43 if(lim<X[i]) continue; 44 sum+=(min(Y[i],lim)-X[i])/Z[i]+1; 45 } 46 return sum; 47 } 48 49 void work() 50 { 51 ll l=1,r=inf,mid,ans=-1; 52 while(l<=r) 53 { 54 mid=(l+r)>>1; 55 if(judge(mid)) ans=mid,r=mid-1; 56 else l=mid+1; 57 } 58 if(ans==-1) puts("no corruption"); 59 else 60 { 61 printf("%lld %lld ",ans,cal(ans)-cal(ans-1)); 62 } 63 } 64 65 int main() 66 { 67 while(gets(s)!=NULL) 68 { 69 if(!strlen(s)) 70 { 71 if(!cnt) continue; 72 work();cnt=0; 73 } 74 else 75 { 76 ++cnt; 77 sscanf(s,"%lld %lld %lld",&X[cnt],&Y[cnt],&Z[cnt]); 78 } 79 } 80 if(cnt) work(); 81 return 0; 82 }