HDOJ 4768 - Flyer 有单调性, 二分解决...

29 篇文章 0 订阅

             题意:

                      有N个社团..有很多的学生..编号从1开始的连续正整数..现在每个社团发传单给其Ai+K*Ci不大于Bi的所有学生发传单...之多可能有一个学生拿了奇数个传单..请求出这个学生的学号以及他拿的传单数.

             题解:

                      由于之多一个学生的传单数位奇数..代表其他的学生都是偶数..代表在只要有解,必定总传单数位奇数..再想..假设该学生在位置x..用num[i]代表i号学生拿到的传单数量..那么sigma(num[1],num[x])为奇数..并且当k>x..所有的sigma(num[1],num[k])都为奇数..而当k<x时..所有的sigma(num[1],num[k])都为偶数..这样就找到了单调关系.用二分法解决...每次暴力的算出该右界的情况下传单总数...值得注意的是A,B可能为0..处理的时候小心..因为就算能发给0号学生.但0号学生是不存在的..不算发了..


Program:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdlib>
#include<stack>
#include<map>
#define MAXN 20005 
#define ll long long 
#define eps 1e-8
using namespace std;     
struct node
{
     int A,B,C;
}P[MAXN];
ll check(ll x,int n)
{
     ll sum=0,t,A,B,C;
     if (x<0) return 0;
     for (t=1;t<=n;t++)
     { 
            A=P[t].A,B=P[t].B,C=P[t].C;
            if (A>x || A>B) continue; 
            B=min(B,x);
            sum+=(int)((B-A)/(C*1.0))+1;            
     }
     return sum%2;
}
int num(ll x,int n)
{
     int i,sum=0;
     for (i=1;i<=n;i++) 
     {
           if (P[i].A>x || P[i].B<x || (x-P[i].A)%P[i].C) continue;
           sum++;
     }
     return sum;
}
int main()
{   
     int i,n,N; 
     while (~scanf("%d",&n))
     {  
             for (i=1;i<=n;i++) 
             {
                    scanf("%d%d%d",&P[i].A,&P[i].B,&P[i].C);
                    if (!P[i].A) P[i].A+=P[i].C; 
             }
             ll l,r,mid;
             l=0,r=1<<30,r*=2; 
             while (r-l>1)
             {
                    mid=l+r>>1;
                    if (check(mid,n)) r=mid;
                                 else l=mid;
             }       
             N=num(r,n); 
             if (N%2==0) printf("DC Qiang is unhappy.\n");
                    else printf("%I64d %d\n",r,N);        
     } 
     return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值