记录一个菜逼的成长。。
2017 Multi-University Training Contest - Team 3
题目链接
题目大意:
给你长度为
n
的一个
f(l,r,k)
表示
[l,r]的第k大数
求
∑nl=1∑nr=lf(l,r,k)
吐槽一下。。这题暴力竟然能过,有时会T,加输入挂多交几次就能过了。。
暴力做法:
对与每一个
a[i]
,暴力枚举找出它的左边和右边
k
个比它大的。
标程做法:
记录每一个值为
暴力做法:
#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;
}