`
promiser
  • 浏览: 76662 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

bzoj1145: [CTSC2008]图腾totem

    博客分类:
  • oi
阅读更多

http://hi.baidu.com/wjbzbmr/item/03de2de8d025eb07560f1dd0

设f(xxxx)表示排序xxx出现的数量。。
那么我们要求的是f(1324)-f(1243)-f(1432)
注意到f(1243)=f(12xx)-f(1234)。。这两个都很好求。。所以1243解决了。。
但其他两个几乎不可做啊。。题目既然让我们相减,这两个式子必然是有所关联的。。
f(1324)-f(1432)
我们尝试着在两边都+上一个f。。
(f(1324)+f(1423))-(f(1432)+f(1423))
=f(1x2x)-f(14xx)
这两个都是线段树可做的。。所以问题就解决了。。。
1x2x的做法是把所有数字从小到大加入序列。。
当加入数字x的时候,没有加入的就是空白,它一定比x大
对每个数字维护它后面的空白数量。
然后维护子段和。。
考虑当前加入的数字为2就差不多了。。

14xx的做法
所有数字从左到右加入按大小组成的序列。。。
那么考虑当前的数字为4.。那么xx必然是它和1之间的空白。。
那么维护每个数字后面的空白数量,的空白的数量的平方
并对这两个进行子段和的维护。。。。

 

代码完全抄袭某神

const int N = 200010, Mod = 16777216;
int n, Dat[N];
LL Cnt[N], Count[6][N], Ans;

inline void Input() {
	scanf("%d", &n);
	For(i, 1, n) scanf("%d", &Dat[i]);
}

inline void Plus(int x) {
	Ans = (Ans + x) % Mod;
}

#define lowbit(x) ((x) & (-(x)))

inline void Change(LL *A, int V, LL Val) {
	for( ; V <= n; V += lowbit(V)) A[V] += Val;
}

inline LL Ask(LL *A, int V) {
	LL Ret = 0;
	for( ; V; V -= lowbit(V)) Ret += A[V];
	return Ret;
}

inline LL C(LL A, int B) {
	if(A < B) return 0;
	if(B == 2) return A * (A - 1) / 2;
	return A * (A - 1) * (A - 2) / 6;
}

#undef lowbit

inline void Solve() {
	Ans = 0;
	
	Ford(i, n, 1) {
		int T = Cnt[i] = Ask(Count[0], n) - Ask(Count[0], Dat[i]);
		Plus(Ask(Count[2], n) - Ask(Count[2], Dat[i]) - C(T, 3));
		Plus(T * (Ask(Count[3], Dat[i]) - C(Ask(Count[0], Dat[i]), 2)));
		Change(Count[0], Dat[i], 1), Change(Count[1], Dat[i], T);
		T = Ask(Count[1], n) - Ask(Count[1], Dat[i]);
		Change(Count[2], Dat[i], T), Change(Count[3], Dat[i], Dat[i] - 1);
	}
	
	For(i, 1, n) {
		int T = Ask(Count[4], Dat[i]);
		Plus(Cnt[i] * (T * i - Ask(Count[5], Dat[i]) - C(T, 2)));
		Change(Count[4], Dat[i], 1), Change(Count[5], Dat[i], i + 1);
	}
	
	cout << (Ans + Mod) % Mod;
}

int main() {
	#ifndef ONLINE_JUDGE
	SETIO("1145");
	#endif
	Input();
	Solve();
	return 0;
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics