JZOJ 4018 Magic

Description

圆上有 2 ∗ n 个点和连接这些点的 n 条弦,这些弦不会在圆上相交。这2 ∗ n 个点按照在圆上的位置顺序依次标号为 1,2,...,2 ∗ n。
请求出有多少个无序的三元组,使得对应的三条弦可以通过距离的缩放中心对称。

Input

第一行一个数 n (n ≤ 100000)。
接下来 n 行,每行两个数,表示该弦的端点。保证一个数不会出现两次。

Output

输出一个数,表示方案数。
 

Sol 

读不懂题系列,(⊙o⊙)…

原题cf 297E。

题目让我们找三条线段让两两端点距离相等。

不知道为什么,我写了个莫队。

#pragma GCC optimize("-Ofast")
#include<bits/stdc++.h>
#define pii pair<int,int>
#define x first
#define N 2000007
#define y second
using namespace std;
#define sight(x) ('0'<=x&&x<='9')
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;
}
int n,l,r,B;
inline bool cmp(pii X,pii Y) {
    return (X.x/B==Y.x/B)?(X.y<Y.y):(X.x<Y.x);
}
int li,ri,zi,now[N],id[N],s,R[N],s2[N];pii p[N];
inline void add(int x){
    zi+=now[id[x]]?-1:1;
    now[id[x]]^=1;
}
signed main () {
    freopen("magic6.in","r",stdin);
    scanf("%d",&n);
    B=sqrt(7*n);
    for (int i=1;i<=n;i++) {
      read(p[i].x); read(p[i].y);
      if (p[i].x>p[i].y) swap(p[i].x,p[i].y);
      id[p[i].x]=i; id[p[i].y]=i;
    }
    sort(p+1,p+n+1,cmp);
    long long ans=1ll*n*(n-1)/2*(n-2)/3;
    l=1;
    for (int i=1;i<=n;i++) {
        while (r<p[i].y) add(++r);
        while (l>p[i].x) add(--l);
        while (r>p[i].y) add(r--);
        while (l<p[i].x) add(l++);
        li=p[i].y-1-p[i].x-zi>>1;
        ri=n-1-zi-li;
        ans-=1ll*li*ri;
        ans-=1ll*(n-1-zi)*zi/2;
    } 
    printf("%lld\n",ans);
    return 0;
//    for (int i=1;i<=2*n;i++) {
//        
//    }
    return 0;
}

 

 

posted @ 2018-07-14 14:30  泪寒之雪  阅读(307)  评论(0编辑  收藏  举报