现在的位置: 首页 > 综合 > 正文

2013 ACM/ICPC Asia Regional Changsha Online J Candies

2013年09月08日 ⁄ 综合 ⁄ 共 2887字 ⁄ 字号 评论关闭

  感想:比赛一开始,队友就看出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], n, m, sum[N], flag, high,num1[N], arr[N];
bool vis[N];

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[n] = 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;
}

抱歉!评论已关闭.