[NESCAFE27] 探险队

[NESCAFE27] 探险队

题目描述
  N个探险家组队去探索神秘的Nescafe之塔。在路上有个记者问每个探险家参加过的探险活动的数目,而探险家们都不愿意告诉他。于是这个记者得到的回答都是“有A个探险家参过的探险活动比我多,而B个探险家参加过的探险活动比我少。”当然并不一定所有的探险家都说了实话。现在这个杯具的记者想请你帮助他计算至少有多少个探险家说了谎?
输入格式
  第一行是一个正整数N,表示探险队的人数。之后N行每行两个整数A和B,表示一个探险家的答案。
输出格式
  输出一个整数表示答案,即至少有多少人说了谎。
样例输入
3
2 0
0 2
2 2
样例输出
1
数据范围与约定
  对于30%的数据,满足1≤N≤1000。对于100%的数据,满足1≤A, B≤N≤100000。
 
思路:
  dp
  求加权的最多区间不重叠覆盖数
  把N个人想象成一条长度为N的数轴
  那么根据每个人前面的人的个数和后面的人的个数,我们可以确定那个人的位置范围
  而很显然每一个人的位置范围中的人一定和自己参加过的探险活动次数相同,所以说如果两个人的位置范围部分重合(不完全重合),那么就以为这这两个人中有一个在说假话。
  而当两个人的位置范围完全重合时,说明他们去过的探险活动次数可能相等。这时候我们可以把它合并为一个位置范围。
  但是当然,一个从l到r的范围最多合并r-l次,就是说一个[l,r]最多代表l-r+1个人。
  那么如果一个[l,r]重复了>l-r+1次,那么也是有人说谎。对于这种情况我一开始的想法是对于每一个多出l-r+1的[l,r]我把他看做一个独立的[l,r],但是后来发现多出来的完全不需要加入dp都可以。不过我程序也懒得改了。
  然后就是dp计算长度为N的数轴上最多不重叠地放多少个位置范围(对于合并过的位置范围,他的权值是max{l-r+1,该位置范围出现过的次数})。
  我只想到了用数据结构优化到nlogn的做法,不过后来知道这个dp的过程可以在O(n)的时间内完成,不过也懒得再改了(还是我太菜了)
  
Code:
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 #define MAXN 100010
  7 struct Node{
  8     int l,r;
  9     int val,addval;
 10     Node(){}
 11 }T[MAXN<<2];
 12 int l[MAXN],r[MAXN],tmp[MAXN],ord[MAXN],num[MAXN];
 13 int i,j,k,m,n,cnt,x,y,val,temp;
 14 char readc;
 15 void build(int ro,int l,int r){
 16     T[ro].l=l,T[ro].r=r;
 17     T[ro].val=T[ro].addval=0;
 18     if(l==r){
 19         return ;
 20     }
 21     int mid=(l+r)>>1;
 22     build(ro<<1,l,mid);
 23     build((ro<<1)+1,mid+1,r);
 24 }
 25 void pushdown(int ro){
 26     if(T[ro].addval){
 27         int tmp=T[ro].addval;
 28         T[ro<<1].val=max(T[ro<<1].val,tmp); T[(ro<<1)+1].val=max(T[(ro<<1)+1].val,tmp);
 29         T[ro<<1].addval=max(T[ro<<1].addval,tmp); T[(ro<<1)+1].addval=max(T[(ro<<1)+1].addval,tmp);
 30         T[ro].addval=0;
 31     }
 32 }
 33 void update(int ro,int nl,int nr,int sl,int sr,int addval){
 34     if(sr<nl||sl>nr) return;
 35     if(sl<=nl&&sr>=nr){
 36         T[ro].val=max(T[ro].val,addval);
 37         T[ro].addval=max(T[ro].addval,addval);
 38         return;
 39     }
 40     pushdown(ro);
 41     int mid=(nl+nr)>>1;
 42     update(ro<<1,nl,mid,sl,sr,addval);
 43     update((ro<<1)+1,mid+1,nr,sl,sr,addval);
 44     T[ro].val=max(T[ro].val,T[ro<<1].val);
 45     T[ro].val=max(T[ro].val,T[(ro<<1)+1].val);
 46 }
 47 int query(int ro,int nl,int nr,int ql,int qr){
 48     if(qr<nl||ql>nr) return 0;
 49     if(ql<=nl&&qr>=nr) return T[ro].val;
 50     pushdown(ro);
 51     int mid=(nl+nr)>>1;
 52     return max(query(ro<<1,nl,mid,ql,qr),query((ro<<1)+1,mid+1,nr,ql,qr));
 53 }
 54 bool CMP(const int &a,const int &b){
 55     if(r[a]<r[b]){
 56         return true;
 57     }else{
 58         if(r[a]==r[b]){
 59             if(l[a]<l[b]) return true;
 60         }
 61     }
 62     return false;
 63 }
 64 void read(int &n){
 65     while((readc=getchar())&&(readc<48||readc>57));
 66     n=readc-48;
 67     while((readc=getchar())&&(readc>=48&&readc<=57)) n=n*10+readc-48;
 68 }
 69 int main(){
 70     freopen("explore.in","r",stdin);
 71     freopen("explore.out","w",stdout);
 72     read(n);
 73     for(i=1;i<=n;i++){
 74         read(x),read(y);
 75         l[i]=x+1;
 76         r[i]=n-y;
 77         tmp[i]=i;
 78     }
 79     sort(tmp+1,tmp+n+1,CMP);
 80     cnt=0; val=0;
 81     tmp[0]=0,l[0]=r[0]=0;
 82     for(i=1;i<=n;i++){
 83         if(l[tmp[i]]>r[tmp[i]]) continue;
 84         if(l[tmp[i]]<=0||l[tmp[i]]>n||r[tmp[i]]<=0||r[tmp[i]]>n) continue;
 85         if(l[tmp[i]]!=l[ord[cnt]]||r[tmp[i]]!=r[ord[cnt]]){
 86             ord[++cnt]=tmp[i];
 87             val=r[tmp[i]]-l[tmp[i]];
 88             num[cnt]=1;
 89         }else{
 90             if(val){
 91                 val--;
 92                 num[cnt]++;
 93             }else{
 94                 ord[++cnt]=tmp[i];
 95                 num[cnt]=num[cnt-1];
 96             }
 97         }
 98     }
 99     build(1,1,n);
100     for(i=1;i<=cnt;i++){
101         temp=query(1,1,n,1,l[ord[i]]-1);
102         temp+=num[i];
103         update(1,1,n,r[ord[i]],r[ord[i]],temp);
104     }
105     printf("%d\n",n-query(1,1,n,1,n));
106     return 0;
107 }

 

转载于:https://www.cnblogs.com/linxif2008/p/9853386.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值