Meatycake,51nod2117,树状数组

正题

      Portal

      这题挺巧妙的。

      我一开始想的就是考虑一个点对不包含比它大一的点的区间的贡献,在考虑一个点 对包含比它大一的点的区间的贡献,这两个东西可以用一个树状数组套主席树来维护,但是死活卡在2700ms过不了,无奈之下翻看题解。


      题解的做法在这里就不再赘述了:

先考虑区间[l, r]的贡献。将区间排序后共有r-l+1段,如果i和i+1同时这个区间中,那么就可以合并两段为一段。一个所以一个区间的贡献可以转化为:区间的长度-区间中相邻数值的对数。

      再考虑区间[L, R]的meaty值。按照上面的思路,可以转变为:子区间的长度和-每对相邻数值在子区间中的出现次数和。

子区间的长度和为 s(R−L+1) ,s(n)=∑nl=1l⋅(n−l+1)=(n+1)∑nl=1l−∑ni=1l2 。

      每对在[L, R]内的相邻数值会产生贡献:设数值i和i+1的位置为 li,ri(L≤li

      这时候注意到还有[li, ri]在[L, R]内的要求,可以用主席树把L,R当成两个维度,或者直接离线处理。

      复杂度 O(nlogn) 


      也不就比我少个log

#include
using namespace std;

const int N=100010;

templateinline void cmin(IT &a,IT b){if(binline void cmax(IT &a,IT b){if(aa.x||(x==a.x&&(yy){t=x;x=y;y=t;}
		nod[++tot]=node(x,y,0);
	}
	for(int i=1;i<=m;++i){
		scanf("%d %d",&x,&y);
		t=y-x;ans[i]=1ll*(t+1)*(t+2)*(t+3)/6ll;
		nod[++tot]=node(x,y,i);
	}
	solve();
	for(int i=1;i<=m;++i)printf("%lld\n",ans[i]);
	return 0;
}

 

你可能感兴趣的:(Meatycake,51nod2117,树状数组)