[BZOJ3378] [Usaco2004 Open]MooFest 狂欢节(树状数组)

传送门

 

开2个树状数组

一个存的是下标,一个存的是数量

细节。。。看标称吧,懒得说了,好气啊

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 20001 
#define LL long long
#define max(x, y) ((x) > (y) ? (x) : (y))

int n, m;
LL ans, sum, c[N], d[N];

struct node
{
	LL x, v;
}p[N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

inline bool cmp(node x, node y)
{
	return x.v < y.v;
}

inline LL query1(int x)
{
	LL ret = 0;
	for(; x; x -= x & -x) ret += d[x];
	return ret;
}

inline LL query2(int x)
{
	LL ret = 0;
	for(; x; x -= x & -x) ret += c[x];
	return ret;
}

inline void add1(int x, LL y)
{
	for(; x <= m; x += x & -x) d[x] += y;
}

inline void add2(int x, LL y)
{
	for(; x <= m; x += x & -x) c[x] += y;
}

int main()
{
	int i;
	n = read();
	for(i = 1; i <= n; i++)
	{
		p[i].v = read();
		p[i].x = read();
		m = max(m, p[i].x);
	}
	std::sort(p + 1, p + n + 1, cmp);
	for(i = 1; i <= n; i++)
	{
		ans += (p[i].x * query2(p[i].x) - query1(p[i].x)) * p[i].v;
		ans += (sum - query1(p[i].x) - p[i].x * (i - query2(p[i].x) - 1)) * p[i].v;
		sum += p[i].x;
		add1(p[i].x, p[i].x);
		add2(p[i].x, 1);
	}
	printf("%lld\n", ans);
	return 0;
}

  

posted @ 2017-09-16 06:48  zht467  阅读(147)  评论(0编辑  收藏  举报