您的位置:首页 > 编程语言 > Go语言

hoj 2430 Counting the algorithms(树状数组,贪心)

2017-08-11 15:14 686 查看
记录下第一次出现的位置和 两次出现位置的距离差,按照距离差降序排个序,然后扫一遍。。

我看网上别人做法扫一遍,再扫一遍,完事了,效率比我这要高。。。没想到


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

struct node
{
int si,dis;
};
const int MAXN = 200020;

node ns[MAXN/2];
int cnt[MAXN];
int N,num;

bool cmp(const node& a, const node& b)
{
return a.dis > b.dis;
}

int lowBit(int x)
{
return x&-x;
}

int sum(int i)
{
int s = 0;
while(i > 0)
{
s += cnt[i];
i -= lowBit(i);
}
return s;
}

void add(int i, int x)
{
while(i <= N*2)
{
cnt[i] += x;
i += lowBit(i);
}
}

int main()
{
while(scanf("%d",&N) != EOF)
{
memset(cnt,0,sizeof(cnt));
memset(ns,0,sizeof(ns));
for(int i = 1; i <= 2*N; ++i)
{
add(i,1);
scanf("%d",&num);
//记录每个数字第一次出现的下标和两个下标之间的差
if(ns[num].si == 0)
ns[num].si = i;
else
ns[num].dis = i-ns[num].si;
}
sort(ns+1,ns+1+N,cmp);
int res = 0;
for(int i = 1; i <= N; ++i)
{
res += sum(ns[i].si+ns[i].dis)-sum(ns[i].si);
add(ns[i].si,-1);
add(ns[i].si+ns[i].dis,-1);
}
printf("%d\n",res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: