Codeforces Round #215 (Div. 1)

http://codeforces.com/contest/367

A:

注意点细节就行了

B:

太伤了,比赛时候没想太多,果断开启乱搞模式,乱搞了几个哈希函数,5个乱搞!不过赛后煎熬的等待还是RE了。。。不过事实证明我的哈希乱搞是对的,有个地方没开long long判断导致错了!后来去敲正解的,居然也RE在38组!太雷了,m*p是会爆int的,总是这么不小心,所以说细心写代码比速度更更重要,正解是map映射下维护下每个数的cnt值扫一遍判断就可以了,贴一下两个代码。。。


hash乱搞code:

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
        using namespace std; typedef __int64 ll; #define pb push_back const int maxn = 1000000 + 10; ll a[maxn], b[maxn], sum1[maxn], sum2[maxn], sum3[maxn], sum4[maxn], sum5[maxn]; map 
        
          mp; int main() { int n, m, p; scanf("%d%d%d", &n, &m, &p); for(int i = 1;i <= n; i++) scanf("%I64d", &a[i]); for(int i = 1;i <= m; i++) scanf("%I64d", &b[i]); sort(b + 1, b + m + 1); mp[b[1]] = 1; int tmp = 1; for(int i = 2;i <= m; i++) if(b[i] != b[i-1]) mp[b[i]] = ++tmp; ll s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0; for(int i = 1;i <= m; i++) { s1 = s1 + b[i]; if(mp[b[i]] & 1) s2 = s2 + b[i], s3 = s3 - b[i]; else s2 = s2 - b[i], s3 = s3 + b[i]; if(mp[b[i]] % 3 == 0) s4 = s4 - b[i], s5 = s5 + b[i]; else s4 = s4 + b[i], s5 = s5 - b[i]; } for(int i = n;i >= 1; i--) { if(i + p <= n) { sum1[i] = sum1[i+p] + a[i]; if(mp[a[i]] & 1) sum2[i] = sum2[i+p] + a[i], sum3[i] = sum3[i+p] - a[i]; else sum2[i] = sum2[i+p] - a[i], sum3[i] = sum3[i+p] + a[i]; if(mp[a[i]] % 3 == 0) { sum4[i] = sum4[i+p] - a[i]; sum5[i] = sum5[i+p] + a[i]; } else { sum4[i] = sum4[i+p] + a[i]; sum5[i] = sum5[i+p] - a[i]; } } else if(i + p > n){ sum1[i] = a[i]; if(mp[a[i]] & 1) sum2[i] = a[i], sum3[i] = -a[i]; else sum2[i] = -a[i], sum3[i] = a[i]; if(mp[a[i]] % 3 == 0) sum4[i] = -a[i], sum5[i] = a[i]; else sum4[i] = a[i], sum5[i] = -a[i]; } } int ans = 0; vector 
         
           pr; for(int i = 1;i <= n ;i++) if(mp[a[i]]){ ll now1, now2, now3, now4, now5; if(i + (ll)m*p <= n) { now1 = sum1[i] - sum1[i + m*p]; now2 = sum2[i] - sum2[i + m*p]; now3 = sum3[i] - sum3[i + m*p]; now4 = sum4[i] - sum4[i + m*p]; now5 = sum5[i] - sum5[i + m*p]; } else if(i + (ll)(m-1)*p <= n){ // 坑死我了! now1 = sum1[i]; now2 = sum2[i]; now3 = sum3[i]; now4 = sum4[i]; now5 = sum5[i]; } else continue; if(now1 == s1 && now2 == s2 && now3 == s3 && now4 == s4 && now5 == s5) { ans ++; pr.pb(i); } } printf("%d\n", ans); for(int i = 0;i < pr.size(); i++) printf("%d ", pr[i]); puts(""); return 0; } 
          
        
      
      
     
     
    
    
   
   

正解:

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
        using namespace std; typedef __int64 ll; #define pb push_back const int maxn = 200000 + 10; int a[maxn], b[maxn], cnt[maxn], now[maxn]; vector 
        
          pr; map 
         
           mp; int main() { int n, m, p; scanf("%d%d%d", &n, &m, &p); for(int i = 1;i <= n; i++) scanf("%d", &a[i]); for(int i = 1;i <= m; i++) scanf("%d", &b[i]); sort(b + 1, b + m + 1); int tot = 0; for(int i = 1;i <= m; i++) { if(!mp[b[i]]) mp[b[i]] = ++tot; cnt[mp[b[i]]]++; } for(int i = 1;i <= p; i++) { if(i + (ll)(m-1)*p > n) break; int sum = 0, j = i; while(j <= n) { if(mp[a[j]]) { if(now[mp[a[j]]] == cnt[mp[a[j]]]) sum--; now[mp[a[j]]]++; if(now[mp[a[j]]] == cnt[mp[a[j]]]) sum++; } if(j >= m*p + i) { if(mp[a[j - m*p]]) { if(now[mp[a[j - m*p]]] == cnt[mp[a[j - m*p]]]) sum--; now[mp[a[j - m*p]]]--; if(now[mp[a[j - m*p]]] == cnt[mp[a[j - m*p]]]) sum++; } } if(sum == tot) pr.pb(j - (m-1)*p); j += p; } j -= p; sum = 0; while(sum < m) { if(mp[a[j]]) now[mp[a[j]]]--; j -= p; sum++; } } sort(pr.begin(), pr.end()); printf("%d\n", pr.size()); for(int i = 0;i < pr.size(); i++) printf("%d ", pr[i]); puts(""); return 0; } 
          
        
      
      
     
     
    
    
   
   

C题:

比赛时候也想到了这个有点像欧拉回路,因为是在最后时候想出来的,结果是没仔细分析奇偶性,出了后去了趟厕所回来就被hack了,想了下4个不同数的时候答案是8,改了下急忙交了。。。还是没仔细分析。。。结果最后一分钟又被hack了。。这些人hack我好欢乐啊= =总的来说是应对策略太搓,凡事都要仔细仔细再仔细,确保是完全无误的,每次都这样的话会很有进步的,虽然不是表现在算法能力上,这是综合素质。

思路:对于n为奇数的情况,每个点的度数为偶数,所以相当于走一遍欧拉回路就可以了,需要n*(n-1)/2 + 1个位置。n为偶数的话,度数为奇数,那么先把偶数个走完一次欧拉回路,然后剩余的都是度数为1,也就是分别两个两个有边,都需要分开走完,所以需要n个位置,总的需要n*(n-1)/2 - n/2 + n个位置。


code:

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
using namespace std;
typedef __int64 ll;

const int maxn = 100000 + 10;

int w[maxn];

int main() {
    int n, m, q;
    scanf("%d%d", &n, &m);
    for(int i = 1;i <= m; i++)
        scanf("%d%d", &q, &w[i]);
    sort(w + 1, w + m + 1);
    reverse(w + 1, w + m + 1);
    ll cnt = 1;
    while((cnt + 1) * (cnt + 2)/2 + 1 <= n)   cnt += 2;
    ll ans = cnt;
    cnt = 0;
    while((cnt+2)*(cnt+2)/2 <= n) cnt += 2;
    cnt = max(cnt, ans);
    ans = 0;
    for(int i = 1;i <= m && i <= cnt; i++)
        ans += w[i];
    printf("%I64d\n", ans);
    return 0;
}

     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值