【HDU6058】Kanade's sum(暴力 or 链表)

记录一个菜逼的成长。。

2017 Multi-University Training Contest - Team 3

题目链接
题目大意:
给你长度为 n 的一个[1n]的排列。
f(l,r,k) 表示 [l,r]k
nl=1nr=lf(l,r,k)

吐槽一下。。这题暴力竟然能过,有时会T,加输入挂多交几次就能过了。。
暴力做法:
对与每一个 a[i] ,暴力枚举找出它的左边和右边 k 个比它大的。
标程做法:
记录每一个值为i的的位置的前驱和后继,从值1开始枚举,可以保证序列中的数都比当前数大。可以保证向左向右枚举最多只有 k <script type="math/tex" id="MathJax-Element-36">k</script>次,然后删除当前数所在的位置,维护链表。

暴力做法:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for( int i = l; i <= r; i++ )
#define rep0(i,l,r) for( int i = l; i < r; i++ )
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long LL;
typedef pair<int,int> PII;
inline void read(int &x){
    x=0;char p=getchar();
    while(!(p<='9'&&p>='0'))p=getchar();
    while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
const int INF = 0x3f3f3f3f;
const int maxn = 500000 + 10;
int a[maxn];
int L[100],R[100];
int main()
{
  //fin;
  int T;scanf("%d",&T);
  while(T--){
    int n,k;
    scanf("%d%d",&n,&k);
    for( int i = 1; i <= n; i++ ){
      read(a[i]);
    }
    LL ans = 0;
    for( int i = 1; i <= n; i++ ){
      int ind1 = 0,ind2 = 0;
      for( int j = i; j && ind1 < k+1; j-- )if(a[j] >= a[i])L[ind1++] = j;
      for( int j = i; j <= n && ind2 < k+1; j++ )if(a[j] >= a[i])R[ind2++] = j;
      L[ind1++] = 0;R[ind2++] = n+1;
      for( int j = 0; j < ind1-1; j++ ){
        if(k-1-j < ind2-1 && k-1-j >= 0){
          ans += (LL)(R[k-j] - R[k-j-1]) * (L[j] - L[j+1]) * a[i];
        }
      }

    }
    printf("%lld\n",ans);
  }
  return 0;
}

标程做法:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for( int i = l; i <= r; i++ )
#define rep0(i,l,r) for( int i = l; i < r; i++ )
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long LL;
typedef pair<int,int> PII;
inline void read(int &x){
    x=0;char p=getchar();
    while(!(p<='9'&&p>='0'))p=getchar();
    while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
const int INF = 0x3f3f3f3f;
const int maxn = 500000 + 10;
int pos[maxn],pre[maxn],nxt[maxn];
int L[100],R[100];
int n,k;
void erase(int p)
{
  int pp = pre[p];
  int nn = nxt[p];
  if(pp)nxt[pp] = nn;
  if(nn != n+1)pre[nn] = pp;
}
int main()
{
  //fin;
  int T;scanf("%d",&T);
  while(T--){
    scanf("%d%d",&n,&k);
    for( int i = 1,x; i <= n; i++ ){
      read(x);
      pos[x] = i;
    }
    rep(i,1,n)pre[i] = i-1,nxt[i] = i + 1;
    LL ans = 0;
    rep(num,1,n){
      int p = pos[num];
      int ind1 = 0,ind2 = 0;
      for( int d = p; d && ind1 < k + 1; d = pre[d] )L[ind1++] = d;
      for( int d = p; d != n+1 && ind2 < k + 1; d = nxt[d] )R[ind2++] = d;
      L[ind1++] = 0;R[ind2++] = n+1;
      for( int i = 0; i < ind1-1; i++ ){
        if(k-1-i < ind2-1 && k-1-i >= 0){
          ans += (LL)(R[k-i] - R[k-1-i]) * (L[i] - L[i+1]) * num;
        }
      }
      erase(p);
    }
    printf("%lld\n",ans);
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值