[关闭]
@Pinetrie 2019-02-18T00:20:58.000000Z 字数 1033 阅读 1014

I - Infinite Inversions CodeForces - 540E

题意:一个无限的自然数序列进行n次操作,每次交换其中2个位置上的数,求逆序数个数。

题解:操作数很大,如果直接求逆序数个数会超时。而最多有1e5的操作次数,那么可以把点离散化,两个交换点之间加入新的点,该点的权值即是两个点之间的点的个数。离散化后用树状数组直接求其逆序数。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 5 * 100010;
  4. typedef long long ll;
  5. struct node
  6. {
  7. ll a,b;
  8. }nod[maxn];
  9. ll n,tot,cnt,ans;
  10. ll p[maxn],x[maxn],y[maxn],w[maxn],sum[maxn];
  11. ll lowbit(ll x)
  12. {
  13. return x & -x;
  14. }
  15. void addnode(ll x,ll v)
  16. {
  17. while(x <= maxn)
  18. {
  19. sum[x] += v;
  20. x += lowbit(x);
  21. }
  22. }
  23. ll getsum(ll x)
  24. {
  25. ll res = 0;
  26. while(x > 0)
  27. {
  28. res += sum[x];
  29. x -= lowbit(x);
  30. }
  31. return res;
  32. }
  33. int main()
  34. {
  35. scanf("%lld",&n);
  36. for(int i = 1;i <= n;i++)
  37. {
  38. scanf("%lld %lld",&nod[i].a,&nod[i].b);
  39. x[++tot] = nod[i].a;
  40. x[++tot] = nod[i].b;
  41. }
  42. sort(x + 1,x + 1 + tot);
  43. ll len = unique(x + 1,x + 1 + tot) - x - 1;
  44. for(int i = 1;i <= len;i++)
  45. {
  46. y[++cnt] = x[i];
  47. w[cnt] = 1;
  48. if(x[i] + 1 < x[i + 1])
  49. {
  50. y[++cnt] = x[i] + 1;
  51. w[cnt] = x[i + 1] - x[i] - 1;
  52. }
  53. }
  54. for(int i = 1;i <= cnt;i++) p[i] = i;
  55. for(int i = 1;i <= n;i++)
  56. {
  57. int pos1 = lower_bound(y + 1,y + 1 + cnt,nod[i].a) - y;
  58. int pos2 = lower_bound(y + 1,y + 1 + cnt,nod[i].b) - y;
  59. swap(p[pos1],p[pos2]);
  60. }
  61. for(int i = cnt;i >= 1;i--)
  62. {
  63. ans += w[p[i]] * getsum(p[i]);
  64. addnode(p[i],w[p[i]]);
  65. }
  66. printf("%lld\n",ans);
  67. return 0;
  68. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注