2017 多校训练第三场 HDU 6058 Kanade's sum

首先有一个关系:当一个数是第k大的时候,前面有x个比它大的数,那么后面就有k-x-1个比它大的数。然后我们对下标从1开始计算,换算一下,就是程序中的样子。


比赛的时候队友想出了用set来维护。一开始是一个空的set,先插入大的数,那么当之后插入数的时候,他们之间的pos距离就代表它有多少个小于它的,然后根据上面的关系,对于每个数最多使得迭代器跳k次,就可以快速维护了。其实想法和正解差不多,但是因为其迭代器使用不熟练,而且我还死磕自己错误的想法。


题解的思路其实差不多,一开始先维护一个满的链表,然后从小到大删除,每次算完一个数,就在链表里面删除,算x的时候,保证删除的数都比x小,都可以用来算贡献。i和pre[i]和nxt[i]的距离就是小于当前的数的数目+1。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=5e5+5;
int a[maxn],pre[maxn],nxt[maxn],pos[maxn];

int main(int argc, char const *argv[])
{
	int T,n,k;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&k);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			pre[i]=i-1,nxt[i]=i+1,pos[a[i]]=i;;
		}
		pre[0]=0,nxt[n]=n+1;
		ll sum=0;
		for(int j=1;j<=n;j++){
			int x=pos[j];
			int rq[110];
			int lc,rc;
			lc=rc=0;
			for(int i=x;i<=n&&rc<k;i=nxt[i]){
				rq[++rc]=nxt[i]-i;
			}
			ll ans=0;
			for(int i=x;i>0&&lc<k;i=pre[i]){
				lc++;
				if(k-lc+1>rc) continue;
				else ans+=(i-pre[i])*rq[k-lc+1];
			}
			sum+=ans*j;
			pre[nxt[x]]=pre[x];
			nxt[pre[x]]=nxt[x];
		}
		printf("%lld\n",sum);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值