您的位置:首页 > 其它

2013 ACM/ICPC Asia Regional Changsha Online J Candies

2013-09-23 11:27 531 查看
  感想:比赛一开始,队友就看出E是大水题, 我让他们敲, 我去看看G题, 顿时E题就出现过的了, 果然是大水题, 我继续我的G题, 不知道怎么的, 感觉G题有点恶心, 然后直接跳到J题, 一看完就感觉是我的菜(虽然我是搞dp的), 然后推了下规律, 感觉基本差不多了, 于是开始敲了起来, 敲的时候感觉到自己代码能力弱成渣了, 特殊情况一多就直接晕头转向了, 就这样在8点半交了第一发, 然后WA了, 仔细看了下,竟然连测试数据的延伸都过不了, 查了下代码, 原来num1写成num了, 继续第二发, TLE,
想死的心都有了, 然后花了一个小时来优化, 用vis数组来进行标记之前就查询过的, 但是感觉这优化根本就没变化, 然后感觉我的high(上界值)还能优化(之前就没有优化过),改完后就到了9点50了, 测了下数据,都过了, 然后抱着绝望的心情交了最后一发, 红红的AC出现在最上面一行, 啊, 4个小时, 终于A掉了。加油, 我的ACM之路。

 

思路:num是(0 ~ n-1),这题给了An-1 ,An, An+1的和数组, 因为2个左右都只要2个数的和, 所以num2, num5, num8...(反向的 num(n-3), num(n-6)).都可以算出来,

在算出num2, num5 ,num8.....之后,如果还能在除了这些位置上出现一个确定的值, 所以的值就可以确定了, 所以当(n+1)%3==0,并且所有的num值都不知道, 这种情况的所以值不能确定, 其余的情况的所以值全部确定。 能确定的情况直接将所以值算出来, 然后就简单了。 如果是特殊情况就来进行一个搜索进行检查, 先确定这个位置可能的最大值, 然后用这个值来算其他所以的值, 如果其他的数中出现负数肯定不行, 然后继续搜下一个值,high的值需要尽量的优化。

提醒:千万记住特殊位置的考虑, 不然下场会很惨。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define min(a1, b1) (a1)>(b1)?(b1):(a1)
using namespace std;
const int N = 100010;
int num
, n, m, sum
, flag, high,num1
, arr
;
bool vis
;

void solve()
{
num[2] = sum[1] - sum[0];
for(int i=5; i<n; i += 3)
if(num[i]<0)
{
num[i] = sum[i-1] - sum[i-2] + num[i-3];
}

num[n-3] = sum[n-2] - sum[n-1];
for(int i = n - 6; i>=0; i -= 3)
if(num[i]<0)
{
num[i] = sum[i+1] - sum[i+2] + num[i+3];
}

int i;
for(i=0; i<n; ++i)
if((i+1)%3&&num[i]>=0)
{
flag = true;
break;
}
if(flag)
{
if(i == 0|| i == 1)
{
if(i==0)
num[1] = sum[1] - num[0] - num[2];
else
num[0] = sum[1] - num[1] - num[2];
for(int j = 3; j<n; ++j)
num[j] = sum[j-1] - sum[j-2] + num[j-3];
}
else
{
if((i+1)%3==1)
num[i-2] = sum[i-1] - num[i] - num[i-1];
else
num[i-1] = sum[i-1] - num[i-2] - num[i];
for(int j = i - 3; j >= 0; --j)
{
num[j] = sum[j+1] - sum[j+2] + num[j+3];
}
for(int j = i+1; j<n; ++j)
num[j] = sum[j-1] - sum[j-2] + num[j-3];
}
}
}

int judge(int i)
{
num[i] = high;
if(i == 0|| i == 1)
{
if(i==0)
{
num[1] = sum[1] - num[0] - num[2];
if(num[1] < 0)
return false;
}
else
{
num[0] = sum[1] - num[1] - num[2];
if(num[0] < 0)
return false;
}
for(int j = 3; j<n; ++j)
{num[j] = sum[j-1] - sum[j-2] + num[j-3];
if(num[j] < 0)
return false;
}
}
else
{
if((i+1)%3==1)
{num[i-2] = sum[i-1] - num[i] - num[i-1];
if(num[i-2]<0)
return false;
}
else
{
num[i-1] = sum[i-1] - num[i-2] - num[i];
if(num[i-1] < 0)
return false;
}
for(int j = i - 3; j >= 0; --j)
{
num[j] = sum[j+1] - sum[j+2] + num[j+3];
if(num[j] < 0)
return false;
}
for(int j = i+1; j<n; ++j)
{num[j] = sum[j-1] - sum[j-2] + num[j-3];
if(num[j] < 0)
return false;
}
}
return true;
}

int main(void)
{
while(scanf("%d",&n) != EOF)
{
for(int i=0; i<n; ++i)
scanf("%d", num+i);
num
= 0;
for(int i=0; i<n; ++i)
scanf("%d", sum+i);
scanf("%d",&m);
int k;
flag = false;
solve();
if(!flag)
{
for(int i=0; i<n; ++i)
{
num1[i] = num[i];
vis[i] = false;
}
while(m--)
{
scanf("%d",&k);
if(num1[k] >= 0)
printf("%d\n",num1[k]);
else if(vis[k])
{
printf("%d\n",arr[k]);
}
else
{
high = sum[k];
if((k+1)%3==1)
{
if(k-1 >= 0)
{
high = min(high, sum[k] - num[k-1]);
}
if(k+2 < n)
{
high = min(high, sum[k+1] - num[k+2]);
}
}
else
{
if(k-2 >= 0)
{
high = min(high, sum[k-1] - num[k-2]);
}
if(k+1 < n)
{
high = min(high, sum[k] - num[k+1]);
}
}

for(int i=0; i<n; ++i)
num[i] = num1[i];
while(1)
{
if(judge(k))
break;
high --;
}
vis[k] = true;
arr[k] = high;
printf("%d\n",high);
}
}
}
else
{
while(m--)
{
scanf("%d",&k);
printf("%d\n",num[k]);
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: