CF Gym 100463A (树状数组求逆序数)
题意:给你一个序列,和标准序列连线,求交点数。
题解:就是求逆序对个数,用树状数组优化就行了。具体过程就是按照顺序往树状数组了插点(根据点的大小),因为第i大的点应该排在第i位,插进去的时候他前面本该是有i-1个点的,如果少了,那么一定就和这个元素构成了逆序对。
#include<cstdio> #include<cmath> #include<vector> #include<map> #include<set> #include<algorithm> #include<cstring> using namespace std; //#define local typedef long long ll; const int maxn = 1000000+100; #define lowbit(x) ((x)&-(x)) ll C[maxn]; ll n,a,b; void add(ll x,ll d) { while(x <= n) { C[x]+=d; x+=lowbit(x); } } ll sum(ll x) { ll ret = 0; while(x > 0){ ret += C[x]; x-=lowbit(x); } return ret; } ll Count() { ll res = 0; ll ele = b; for(int i = 0; i < n; i++){ ll pre = sum(ele+1); res += ele - pre; add(ele+1,1); ele = (ele+a)%n; } return res; } int main() { #ifdef local freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif // local int cas = 0; while(~scanf("%I64d%I64d%I64d",&n,&a,&b)&&n){ memset(C,0,sizeof(C)); printf("Case %d: %I64d\n",++cas,Count()); } return 0; }