Gym 100796E Permutation Polygon [树状数组]

来源:互联网 发布:云计算安全技术与应用 编辑:程序博客网 时间:2024/05/19 06:48

Description

  • There are n cities in Regularia, Alice's homeland. They are located at the vertices of a regular n-gon. The cities are numbered from 1 ton in a clockwise order (see the figure).

    The people of Regularia love Alice so much that they made her the queen of the country. Alice wants to prove herself, so she has ordered a construction of a new highway system connecting cities of Regularia. Alice has come up with a plan to build the highways, which is ann-permutation p1, p2, ..., pn. Specifically, for a city numbered i, Alice wants to build a highway between the cities i and pi, where piis the number of some other city. A highway is a straight line connecting two cities. According to Alice's plan, any two cities will be connected by no more than a single highway.

    Of course, some of the highways may intersect one another. Two highways are said to intersect if and only if there is a unique point that belongs to both of the highways and is not a city. This point is called a junction of the two highways. Even if more than two highways meet at a single point, each pair has its own separate junction. As a complicated and expensive interchange has to be built at each junction, Alice is interested in the total number of junctions in her plan. Help her find this number!

    For example, the plan for a permutation 4, 1, 5, 3, 2 is shown in the figure.

  • Input

    The first line contains a single integer n, the number of cities in Regularia (3 ≤ n ≤ 105). The next line contains n space-separated integers p1, p2, ..., pn, which is a permutation of length n. It is guaranteed that i ≠ pi for any i and that no two cities will be connected by more than a single highway.

    Output

    Output a single integer — the total number of junctions in Alice's plan.

    大致题意:

    一个正N边形,每个顶点的标号为1..N,现在给出一些<X,Y>表示两点有一条连线,问在多边形内部有多少个交点。(多个点在同一位置算多个)

    解法:

    可以发现如果两条线有交点,那么其两端的 index (x,y)(保证X<Y),肯定是交错的,即如同 x'  X  y'  Y ,那么可以考虑对X排序,保证x'比当前枚举的X小,然后查看X到Y之间(不包括两端),有多少个 y’ 即可,这个过程可以用树状数组实现。

    代码:

    #include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#include<iostream>#include<stdlib.h>#include<set>#include<map>#include<queue>#include<vector>#include<bitset>#pragma comment(linker, "/STACK:1024000000,1024000000")template <class T>bool scanff(T &ret){ //Faster Input    char c; int sgn; T bit=0.1;    if(c=getchar(),c==EOF) return 0;    while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();    sgn=(c=='-')?-1:1;    ret=(c=='-')?0:(c-'0');    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');    if(c==' '||c=='\n'){ ret*=sgn; return 1; }    while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;    ret*=sgn;    return 1;}#define inf 1073741823#define llinf 4611686018427387903LL#define PI acos(-1.0)#define lth (th<<1)#define rth (th<<1|1)#define rep(i,a,b) for(int i=int(a);i<=int(b);i++)#define drep(i,a,b) for(int i=int(a);i>=int(b);i--)#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)#define mem(x,val) memset(x,val,sizeof(x))#define mkp(a,b) make_pair(a,b)#define findx(x) lower_bound(b+1,b+1+bn,x)-b#define pb(x) push_back(x)using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> pii;struct node{    int x,y;    bool operator < (const node temp)const{        if(x==temp.x)return y<temp.y;        return x<temp.x;    }}a[100100];int n;int c[100100];#define lowbit(x) (x&(-x))void add(int x){    for(int i=x;i<=n;i+=lowbit(i))c[i]++;}int getsum(int l,int r){    int s1=0,s2=0;    for(int i=l-1;i>0;i-=lowbit(i))s1+=c[i];    for(int i=r;i>0;i-=lowbit(i))s2+=c[i];    return s2-s1;}int lor[100100][2];int main(){    scanff(n);    rep(i,1,n){        int x=i;        int y;        scanff(y);        if(x>y)swap(x,y);        a[i].x=x;        a[i].y=y;    }    ll ans=0;    sort(a+1,a+1+n);    rep(i,1,n){        if(i==1||a[i].x!=a[i-1].x)lor[a[i].x][0]=i;        if(i==n||a[i].x!=a[i+1].x)lor[a[i].x][1]=i;    }    rep(i,1,n){        if(lor[i][0]==0)continue;        rep(j,lor[i][0],lor[i][1]){            ans+=ll(getsum(a[j].x+1,a[j].y-1));        }        rep(j,lor[i][0],lor[i][1]){            add(a[j].y);        }    }    printf("%lld\n",ans);    return 0;}



    0 0
    原创粉丝点击