zoukankan      html  css  js  c++  java
  • 2013 ACM/ICPC Asia Regional Changsha Online J Candies

    AC了,但是不知道为什么,但是恶心的不得了~最近写代码,思路都非常清晰,但是代码各种bug~T.T~
    说说思路吧:二分~330ms~  小队友fribbi的思路是离线250msAC~

    预处理solve函数(让能求出来的尽量都求出来)-->a[2]a[n-3]已知

    ①已知a[i]可知a[i+3]
    ②已知a[i] a[i-1] 或者a[i] a[i+1]或者a[i+1] a[i-1]可知全部

    ③已知a[0]a[1]a[n-2]a[n-1]可知全部

    提问:

    ①已知则直接输出,不存在a[i+1] a[i-1]已知a[i]未知这种情况,solve已处理

    ②已知前面或者后面的一个 二分检测(因为至少a[2+2*k],k=0,1,2...已知)

    ③提问是0位置或者n-1位置 二分检测

    检测时候用test数组,因为检测时有赋值,不能对num数组赋值,否则会影响下次的测试~

    巨恶心的代码(自己给把自己恶心到了)~

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cmath>
      4 #include <algorithm>
      5 using namespace std;
      6 #define N 100000
      7 #define back num[i]=sum[i-1]-num[i-1]-num[i-2]
      8 #define front num[i]=sum[i+1]-num[i+1]-num[i+2]
      9 int num[N+10];
     10 int sum[N+10];
     11 int test[N+10];
     12 int n;
     13 int cal(int id){//make sure id>=2&&id<n-2
     14 //return 1 O(N)全部求出来了,return 0,代表只求出了一部分的数字
     15     int i,least;
     16     if(num[id-1]!=-1){//左边已知
     17         for(i=id-2;i>=0;i--) front;for(i=id+1;i<n;i++) back;return 1;
     18     }
     19     else if(num[id+1]!=-1){//右边已知
     20         for(i=id-1;i>=0;i--) front;for(i=id+2;i<n;i++) back;return 1;
     21     }
     22     else{//左右都未知
     23         least=sum[id+1]-num[id];
     24         for(i=id+3;i<n&&num[i]==-1;i+=3){
     25             num[i]=sum[i-1]-least;if(i+1<n) least=sum[i+1]-num[i];
     26         }
     27         least=sum[id-1]-num[id];
     28         for(i=id-3;i>0&&num[i]==-1;i-=3){
     29             num[i]=sum[i+1]-least;if(i-1>=0) least=sum[i-1]-num[i];
     30         }
     31         return 0;
     32     }
     33 }
     34 void solve(){
     35     int i,j;
     36     if(num[0]!=-1){num[1]=sum[0]-num[0];for(i=2;i<n;i++) back;}
     37     else if(num[1]!=-1){num[0]=sum[0]-num[1];for(i=2;i<n;i++)back;}
     38     else if(num[n-1]!=-1){num[n-2]=sum[n-1]-num[n-1];for(i=n-3;i>=0;i--)front;}
     39     else if(num[n-2]!=-1){num[n-1]=sum[n-1]-num[n-2];for(i=n-3;i>=0;i--)front;}
     40     else for(j=0,i=2;i<n-2&&!j;i++) if(num[i]!=-1) j=cal(i);
     41     //j相当于flag,flag=1代表已经全部求出,不需要继续循环了
     42     return ;
     43 }
     44 int backword(int i,int id){
     45     for(;i<n;i++){
     46         if(test[i]==-1) test[i]=sum[i-1]-test[i-1]-test[i-2];
     47         if(test[i]<0) if(test[i]<0) return (i%3==id%3)?1:2;
     48     }
     49     return 0;//合法
     50 }
     51 int forward(int i,int id){
     52     for(;i>=0;i--){
     53         if(test[i]==-1) test[i]=sum[i+1]-test[i+1]-test[i+2];
     54         if(test[i]<0) return (i%3==id%3)?1:2;
     55     }
     56     return 0;//合法
     57 }
     58 bool check(int id,int key,int type){
     59     int i,j;
     60     for(i=0;i<n;i++) test[i]=num[i];test[id]=key;
     61     //test[i-1]已知 test[i]测试 向两边检查
     62     if(type==0){
     63         if(backword(id+1,id)==2||forward(id-2,id)==2) return 0;
     64     }
     65     //test[i+1]已知 test[i]测试 向两边检查
     66     else if(type==1){
     67         if(backword(id+2,id)==2||forward(id-1,id)==2) return 0;
     68     }
     69     //test[0]测试,test[1]未知,test[2]已知 向后检查
     70     else if(type==2){
     71         test[1]=sum[1]-test[0]-test[2];
     72         if(backword(3,id)==2) return 0;
     73     }
     74     //test[n-1]测试,test[n-2]未知,test[n-3]已知 向前检查
     75     else {
     76         test[n-2]=sum[n-2]-test[n-1]-test[n-3];
     77         if(forward(n-3,id)==2) return 0;
     78     }
     79     return 1;
     80 }
     81 int bin(int type,int id){//二分检查最大值,能大则大
     82     int left=0,right=sum[id],mid,ans=left;
     83     while(left<=right){
     84         mid=(left+right)/2;
     85         if(check(id,mid,type))//正好 太小
     86             {left=mid+1;ans=mid;}
     87         else right=mid-1;//太大
     88     }
     89     return ans;
     90 }
     91 int main(){
     92     int i,j;
     93     int p,q;
     94     int res;
     95     while(scanf("%d",&n)!=EOF){
     96         for(i=0;i<n;i++) scanf("%d",&num[i]);
     97         for(i=0;i<n;i++) scanf("%d",&sum[i]);
     98 
     99         num[2]=sum[1]-sum[0];//导火索
    100         num[n-3]=sum[n-2]-sum[n-1];//导火索
    101 
    102         solve();//把所有的可以计算出来的全部计算出来
    103 
    104         scanf("%d",&q);
    105         while(q--){
    106             scanf("%d",&p);
    107             if(num[p]!=-1) res=num[p];//num[i]已知
    108             else if(p-1>=0&&num[p-1]!=-1) res=bin(0,p);//num[i-1]已知
    109             else if(p+1<n&&num[p+1]!=-1)  res=bin(1,p);//num[i+1]已知
    110             else if(p==0)   res=bin(2,p);//num[0]未知,num[1]未知,num[2]已知
    111             else if(p==n-1) res=bin(3,p);//num[n-1]未知,num[n-2]未知,num[n-3]已知
    112             printf("%d
    ",res);
    113         }
    114     }
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    ftp 传文件完整代码(二)
    生成文件 权限 以及ftp 传数据(一)
    定时任务配置
    发送电子邮件遇到问题
    mysql 主从分离配置
    知道开始时间结束时间 计算这之间一共多少天
    mysql 语句集(二)
    mysql 的sql文件导出导入
    mysql 批量添加 更新
    Spring Boot中如何干掉if else
  • 原文地址:https://www.cnblogs.com/-sunshine/p/3337393.html
Copyright © 2011-2022 走看看