【题意】
有N个数,非负。其值Ai如果不确定则为-1,否则给定一非负数。另外给定N个数,非负,第i个数Si为与第i个数相邻的左右两个和它自身的值的和。即S1 = A1 + A2, S2 = A1 + A2 + A3....
询问M次,每次询问第i个数Ai可以取得的最大值。
【分析】
从前往后,对于第i%3 == 0的数的值是可以确定的。比如A3 = S2 - S1。
从后往前,对于第(n-i+1)%3 == 0的数的值也是可以确定的。同理
这样当n%3 == 0和n%3 == 1的数列是可以确定的了。
当n % 3 ==2时,只能从前往后确定i%3==0的数。考察
A1 + A2 = S2 - A3 = B1
A2 + A4 = S3 - A3 = B2
A4 + A5 = S5 - A6 = B3
A5 + A7 = S6 - A6 = B4
.....
以上方程组的秩为未知数个数 - 1,可得自由变量个数为1,那么确定其中一个变量取值范围即可。(膜拜队友^.^)
考察A1的取值范围,
A2 = B1 - A1 = K1 - A1
A4 = B2 - A2 = B2 - B1 + A1 = K2 + A1
A5 = B3 - A4 = B3 - B2 + B1 - A1 = K3 - A1
A7 = B4 - A5 = B4 - B3 + B2 - B1+ A1 = K4 + A1
.....
需要保证所有数非负,那么A1取得最大值为min{K1,K3,K5,.....},min{}数据保证为非负
同理,A1 取得最小值应该为所有min{K2,K4,K6,....},如果min{}值为非负,那么A1取0,如果该值为负,A1取其绝对值。
这样就能确定A1的最大、最小值。
当A1取最大值时,相应A4、A7、。。。也取得最大值。
当A1取最小值时,A2取得最大值,那么A5.。。。也取得最大值。
问题可解。
O(N)求出B1、K1....
总复杂度O(N)
【Mark】
比赛的时候写了个暴力来对拍。。。可惜比赛的时候把A1的最小值确定错了。。。跪!
代码写了近400行,膜拜100行内的大神!
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 6 using namespace std; 7 8 #define LL long long 9 #define inf 100000000 10 const int maxn = 100010; 11 12 int n ,m; 13 LL a[maxn];//给定的A数组 14 LL seq[maxn];//给定的 15 16 LL sum[maxn];//从前往后求和 17 LL sss[maxn];//从后往前求和 18 LL b[maxn];//能确定的数的值,不能确定为-1 19 LL c[maxn];//求出A1、A4。。。。等i%3==1的数的最大值 20 LL d[maxn];//求出A2、A5。。。。等i%3==2的数的最大值 21 LL bb[maxn]; //题解中的B数组 22 LL ff[maxn];//题解中的K数组 23 24 /***********以下为暴力对拍******************/ 25 bool check(int pos,LL val) 26 { 27 for (int i=1; i<=n; i++) 28 { 29 c[i] = b[i]; 30 } 31 c[pos] = val; 32 if (pos % 3==1) 33 { 34 if (pos == 1) 35 { 36 c[pos+1] = seq[pos+1] - c[pos] - c[pos+2]; 37 } 38 else 39 { 40 c[pos+1] = seq[pos] - c[pos] - c[pos-1]; 41 } 42 if (c[pos+1]<0) 43 return false; 44 for (int i=pos+2; i<=n; i++) 45 { 46 c[i] = seq[i-1] - c[i-1] - c[i-2]; 47 if (i % 3 == 0) 48 { 49 if (b[i] != c[i]) 50 return false; 51 } 52 if (c[i] < 0) 53 return false; 54 } 55 for (int i=pos-1; i>=1; i--) 56 { 57 c[i] = seq[i+1] - c[i+1] - c[i+2]; 58 if (i % 3 == 0) 59 { 60 if (b[i] != c[i]) 61 return false; 62 } 63 if (c[i] < 0) 64 return false; 65 } 66 } 67 else if (pos % 3 == 2) 68 { 69 if (pos == n) 70 { 71 c[pos-1] = seq[pos-1] - c[pos] - c[pos-2]; 72 } 73 else 74 { 75 c[pos-1] = seq[pos] - c[pos] - c[pos+1]; 76 } 77 if (c[pos-1]<0) 78 return false; 79 for (int i=pos+1; i<=n; i++) 80 { 81 c[i] = seq[i-1] - c[i-1] - c[i-2]; 82 if (i % 3 == 0) 83 { 84 if (b[i] != c[i]) 85 return false; 86 } 87 if (c[i] < 0) 88 return false; 89 } 90 for (int i=pos-2; i>=1; i--) 91 { 92 c[i] = seq[i+1] - c[i+1] - c[i+2]; 93 if (i % 3 == 0) 94 { 95 if (b[i] != c[i]) 96 return false; 97 } 98 if (c[i] < 0) 99 return false; 100 } 101 } 102 else 103 { 104 return true; 105 } 106 return true; 107 } 108 109 LL solve(int pos) 110 { 111 if (pos % 3 == 1) 112 { 113 LL res = inf; 114 if (pos == 1) 115 { 116 res = min(res, seq[2] - b[3]); 117 res = min(res,seq[1]); 118 } 119 else 120 { 121 res = min(res, seq[pos] - b[pos-1]); 122 res = min(res, seq[pos-1] - b[pos-1]); 123 if (pos + 1 < n) 124 res = min(res ,seq[pos+1] - b[pos + 2]); 125 else 126 res = min(res,seq[n]); 127 } 128 // printf("resw = %lld\n",res); 129 while (res>0) 130 { 131 if (check(pos, res)) 132 break; 133 res--; 134 } 135 return res; 136 } 137 else if (pos % 3 ==2) 138 { 139 LL res = inf; 140 if (pos == 2) 141 { 142 res = min(res,seq[1]); 143 res = min(res,seq[2] - b[3]); 144 res = min(res,seq[3] - b[3]); 145 } 146 else 147 { 148 res = min(res,seq[pos-1] - b[pos - 2]); 149 if (pos<n) 150 { 151 res = min(res, seq[pos] - b[pos+1]); 152 res = min(res, seq[pos+1] - b[pos + 1]); 153 } 154 else 155 { 156 res = min(res, seq[n]); 157 } 158 } 159 //printf("%lld\n",res); 160 while (res >0) 161 { 162 if (check(pos,res)) 163 break; 164 res--; 165 } 166 return res; 167 } 168 else 169 { 170 // while (1); 171 } 172 return 0; 173 } 174 175 /*************以上为暴力对拍**************/ 176 177 178 int main() 179 { 180 while (scanf("%d",&n)==1) 181 { 182 memset(a,-1,sizeof(a)); 183 memset(c,-1,sizeof(c)); 184 for (int i=1; i<=n; i++) 185 { 186 scanf("%lld",&a[i]); 187 } 188 for (int i=1; i<=n; i++) 189 { 190 scanf("%lld",&seq[i]); 191 } 192 193 memset(sum,-1,sizeof(sum)); 194 sum[0] = 0; 195 sum[2] = seq[1]; 196 for (int i=3; i<=n; i++) 197 { 198 if (i%3 == 1) 199 { 200 continue; 201 } 202 else 203 { 204 sum[i] = sum[i-3] + seq[i-1]; 205 } 206 } 207 memset(sss,-1,sizeof(sss)); 208 sss[n+1] = 0; 209 sss[n-1] = seq[n]; 210 for (int i=n-2; i>=1; i--) 211 { 212 if ((n - i+1)%3 == 1) 213 { 214 continue; 215 } 216 else 217 { 218 sss[i] = sss[i+3] + seq[i+1]; 219 } 220 } 221 222 memset(b,-1,sizeof(b)); 223 for (int i=1; i<=n; i++) 224 { 225 if (i%3 == 0) 226 { 227 b[i] = sum[i] - sum[i-1]; 228 } 229 } 230 for (int i=n; i>=1; i--) 231 { 232 if ((n - i + 1)%3 == 0) 233 { 234 b[i] = sss[i] - sss[i+1]; 235 } 236 } 237 238 /********以下分类讨论求解***********/ 239 if (n % 3 == 2) 240 { 241 //考虑某个非i%3==0的数值确定,那么整个数组也确定。否则求最大最小值 242 int pos = -1; 243 for (int i=1; i<=n; i++) 244 { 245 if (a[i]!=-1) 246 { 247 if (b[i]!=-1) 248 { 249 while (a[i] != b[i]) {} 250 continue; 251 } 252 else 253 { 254 b[i] = a[i]; 255 pos = i; 256 break; 257 } 258 } 259 } 260 261 if (pos != -1) 262 { 263 if (pos%3 == 1) 264 { 265 b[pos+1] = seq[pos + 1] - b[pos] - b[pos + 2]; 266 for (int i=pos+3; i<=n; i++) 267 { 268 b[i] = seq[i - 1] - b[i-1] - b[i-2]; 269 } 270 for (int i = pos - 1; i>=1; i--) 271 { 272 b[i] = seq[i+1] - b[i+1] - b[i+2]; 273 } 274 } 275 else 276 { 277 b[pos-1] = seq[pos] - b[pos] - b[pos + 1]; 278 for (int i=pos+2; i<=n; i++) 279 { 280 b[i] = seq[i-1] - b[i-1] - b[i-2]; 281 } 282 for (int i=pos-1; i>=1; i--) 283 { 284 b[i] = seq[i+1] - b[i+1] - b[i+2]; 285 } 286 } 287 } 288 else 289 { 290 //求最大最小值 291 int cnt = 0; 292 memset(bb,-1,sizeof(bb)); 293 b[0] = 0; 294 for (int i=1; i<n; i++) 295 { 296 if (i%3==1) 297 { 298 bb[++cnt] = seq[i] - b[i-1]; 299 } 300 else if (i %3==2) 301 { 302 bb[++cnt] = seq[i+1] - b[i+1]; 303 } 304 } 305 ff[0] = 0; 306 for (int i=1; i<=cnt; i++) 307 { 308 ff[i] = bb[i] - ff[i-1]; 309 // printf("ff%d = %lld\n",i,ff[i]); 310 } 311 312 c[1] = seq[1]; 313 for (int i=1; i<=cnt; i++) 314 { 315 if(i % 2 ==1) 316 { 317 c[1] = min(c[1],ff[i]); 318 } 319 } 320 // printf("c = %lld\n",c[1]); 321 c[2] = seq[1] - c[1]; 322 for (int i=3; i<=n; i++) 323 { 324 c[i] = seq[i-1] - c[i-1] - c[i-2]; 325 } 326 327 328 d[1] = 0; 329 for (int i=1; i<=cnt; i++) 330 { 331 if (i%2==0) 332 { 333 if (ff[i]<0) 334 { 335 d[1] = max(d[1], -ff[i]); 336 } 337 } 338 } 339 // printf("c = %lld = %lld\n",c[1],d[1]); 340 d[2] = seq[1] - d[1]; 341 for (int i=3; i<=n; i++) 342 { 343 d[i] = seq[i-1] - d[i-1] - d[i-2]; 344 } 345 // printf("%lld %lld\n",d[1],d[2]); 346 } 347 } 348 else if (n % 3 == 1) 349 { 350 b[1] = seq[2] - b[2] - b[3]; 351 for (int i=4; i<=n; i++) 352 { 353 if (i % 3 == 1) 354 { 355 b[i] = seq[i-1] - b[i-1] - b[i-2]; 356 } 357 } 358 } 359 else 360 { 361 b[2] = seq[2] - b[1] - b[3]; 362 for (int i=5; i<=n; i++) 363 { 364 if (i % 3 == 2) 365 { 366 b[i] = seq[i-1] - b[i-1] - b[i-2]; 367 } 368 } 369 } 370 scanf("%d",&m); 371 for (int i=1; i<=m; i++) 372 { 373 int id; 374 scanf("%d",&id); 375 id++; 376 if (b[id]!=-1) 377 { 378 printf("%lld\n",b[id]); 379 } 380 else 381 { 382 //LL tmp = solve(id); 383 LL tmp1 = -1; 384 if (id % 3==1) 385 { 386 tmp1 = c[id]; 387 } 388 else 389 { 390 tmp1 = d[id]; 391 } 392 //printf("%lld tmp1 = %lld\n",tmp,tmp1); 393 printf("%lld\n",tmp1); 394 } 395 } 396 } 397 return 0; 398 }