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 }