洛谷 P3660 USACO17FEB Why Did the Cow Cross the Road III 题解

打印 上一主题 下一主题

主题 1055|帖子 1055|积分 3165

题意

有一个圆,圆周上按顺时针方向给出                                   2                         n                              2n                  2n个点。第                                   i                              i                  i个点的颜色是                                   c                         o                         l                         o                                   r                            i                                       color_i                  colori​,此中数据包管                                   1                         ≤                         c                         o                         l                         o                                   r                            i                                  ≤                         n                              1\le color_i\le n                  1≤colori​≤n,而且每种不同的颜色有且只有两个点。不存在位置重叠的点。在颜色雷同的两个点之间连一条边(线段)。
求有多少对边是交叉的?
                                    1                         ≤                         n                         ≤                         50000                              1\le n \le 50000                  1≤n≤50000

思路

转换一下题意,把所谓的“圆圈”拉平成一条直线上的                                   2                         n                              2n                  2n个点,以相等的两个数的下标作为两头点连一条线段,求线段存在交集且不存在全包含关系的对数。

遇到线段覆盖题目,可以考虑使用树状数组来维护区间内的点数个数。罗列到一条线段,就在树状数组上给两头端点分别加一;计算一条线段                                   i                         (                         l                         e                         −                         r                         i                         )                              i(le-ri)                  i(le−ri)的贡献就是                                   q                         u                         e                         r                         y                         (                         r                                   i                            i                                  −                         1                         )                         −                         q                         u                         e                         r                         y                         (                         l                                   e                            i                                  )                              query(ri_i-1)-query(le_i)                  query(rii​−1)−query(lei​)
如许算难道不会算重吗?
可以先考虑处置惩罚长度更长的线段,假如一条线段                                   b                              b                  b被线段                                   a                              a                  a完全覆盖,必然有                                   l                         e                                   n                            a                                  >                         l                         e                                   n                            b                                       len_a>len_b                  lena​>lenb​,此时会先处置惩罚                                   a                              a                  a再处置惩罚                                   b                              b                  b,就不会多算                                   b                              b                  b的两头节点了。
对于别的的线段,要么与线段                                   a                              a                  a自己相离,固然不会计入贡献,要么一端端点在开区间                                   (                         l                                   e                            a                                  ,                         r                                   i                            a                                  )                              (le_a,ri_a)                  (lea​,ria​)内,计入贡献为                                   1                              1                  1。
代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define ls u<<1
  5. #define rs u<<1|1
  6. const ll N=1e5+2;
  7. ll n,ans;
  8. struct seg
  9. {
  10.         ll l,r;
  11. }a[N];
  12. bool cmp(seg x,seg y)
  13. {
  14.         return x.r-x.l>y.r-y.l;
  15. }
  16. struct BT
  17. {
  18.         ll T[N];
  19.         ll lowbit(ll x)
  20.         {
  21.                 return x&(-x);
  22.         }
  23.         void add(ll x,ll k)
  24.         {
  25.                 for(int i=x;i<=n*2;i+=lowbit(i))
  26.                 T[i]+=k;
  27.         }
  28.         ll query(ll x)
  29.         {
  30.                 ll ret=0;
  31.                 for(int i=x;i>=1;i-=lowbit(i))
  32.                 ret+=T[i];
  33.                 return ret;
  34.         }
  35. }B;
  36. int main()
  37. {
  38.         scanf("%lld",&n);
  39.         for(int i=1;i<=n*2;i++)
  40.         {
  41.                 ll x;
  42.                 scanf("%lld",&x);
  43.                 if(!a[x].l)a[x].l=i;
  44.                 else a[x].r=i;
  45.         }
  46.         sort(a+1,a+n+1,cmp);
  47.         for(int i=1;i<=n;i++)
  48.         {
  49.                 B.add(a[i].l,1);
  50.                 B.add(a[i].r,1);
  51.                 ans+=B.query(a[i].r-1)-B.query(a[i].l);
  52.         }
  53.         printf("%lld",ans);
  54.         return 0;
  55. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

自由的羽毛

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表