codefroces 297E Mystic Carvings

problem:
一个圆上依次有1~2*n的数字。每个数字都有且只有另一个数字与他相连。选出三条线,使得每条线的两端之间隔的最少点(只包括被选择的6个点)的个数相等。
输入输出格式
输入格式:

The first line contains integer n(3<=n<=10^5) — the number of lines.

Each of the following n n n lines contains two integers ai​,bi​ (1<=ai,bi<=2n), which means that there is a line carved on the ice connecting the ai –th and bi​ –th endpoint.

It's guaranteed that each endpoints touches exactly one line.

输出格式:

Print the number of ways to build the caves.

Please, do not write the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.

输入输出样例
输入样例#1:

4
5 4
1 2
6 7
8 3

输出样例#1:

2

输入样例#2:

8
1 7
2 4
3 9
5 11
6 8
10 16
13 15
14 12

输出样例#2:

6

说明

The second sample corresponds to the figure in the problem statement.

六个点三条边有以下五种可能:


明显只有第1个和第4个可以。但是这2个情况不好求

可以求出总方案再减去不合法方案

此题有两种写fa

第一种是树状数组

假设当前直线i a->b(a<b)

在直线左边的直线数为x,右边的直线数为y,与i相♂蕉的直线数为z

显然有x+y+z+1=n

第3种情况就是x*y

第2,5种是(x+y)*z

但是因为每个点都有边连出,且圆上无

所以z=b-a-1-2*x

第二种是主席树,了解一下

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long lol;
 8 lol c[200001],n,m;
 9 int a[200001],b[200001],p[200001];
10 lol ans1,ans2,ans;
11 void add(int x,int d)
12 {
13   while (x<=m)
14     {
15       c[x]+=d;
16       x+=(x&(-x));
17     }
18 }
19 int query(int x)
20 {
21   int s=0;
22   while (x)
23     {
24       s+=c[x];
25       x-=(x&(-x));
26     }
27   return s;
28 }
29 int main()
30 {int i;
31   cin>>n;
32   m=2*n;
33   for (i=1;i<=n;i++)
34     {
35       scanf("%d%d",&a[i],&b[i]);
36       p[a[i]]=b[i];
37       p[b[i]]=a[i];
38     }
39   for (i=1;i<=m;i++)
40     {
41       if (i<p[i]) continue;
42       int x=query(i)-query(p[i]-1);
43       int z=i-p[i]-1-x*2;
44       add(p[i],1);
45       int y=n-1-x-z;
46       ans1+=x*y;
47       ans2+=(x+y)*z;
48     }
49   ans=n*(n-1)*(n-2)/6;
50   cout<<ans-ans1-ans2/2;
51 }
原文地址:https://www.cnblogs.com/Y-E-T-I/p/8619419.html