Portal

Description

给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\leq5\times10^4)\)次操作:

交换\(a_{p_1},a_{p_2}\),并求\(\sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j](w_{a_i}+w_{a_j})\)。

Solution

树套树/CDQ分治,想锻炼一下代码能力所以写了树套树。

首先这是一个求逆序对的问题,那么我们考虑交换\(a_{p_1},a_{p_2}\)对答案有什么影响。易知只有\(i\in[p_1+1,p_2-1]\)对答案造成影响:

若\(a_i<a_{p_1}\),那么答案减\(a_i+a_{p_1}\);若\(a_i>a_{p_1}\),那么答案加\(a_i+a_{p_1}\)。

若\(a_i<a_{p_2}\),那么答案加\(a_i+a_{p_2}\);若\(a_i>a_{p_2}\),那么答案减\(a_i+a_{p_2}\)。

那么求出\(\{c_1,s_1,c_2,s_2\}\)分别表示区间\([p_1+1,p_2-1]\)内小于/大于\(x\)的\(i\)的个数/\(w_i\)的和,然后就可以根据上两行计算答案的变化。而这可以用树套树来做。

时间复杂度\(O(mlog^2n)\)。

Code

  1. //[TJOI2017]不勤劳的图书管理员
  2. #include <algorithm>
  3. #include <cstdio>
  4. using std::swap;
  5. typedef long long lint;
  6. inline char gc()
  7. {
  8. static char now[1<<16],*s,*t;
  9. if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
  10. return *s++;
  11. }
  12. inline int read()
  13. {
  14. int x=0; char ch=gc();
  15. while(ch<'0'||'9'<ch) ch=gc();
  16. while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
  17. return x;
  18. }
  19. const int N=5e4+10;
  20. const int P=1e9+7;
  21. int n,m,a[N],w[N];
  22. namespace init
  23. {
  24. int tr1[N],tr2[N];
  25. void add(int x,int v) {while(x<=n) tr1[x]++,tr2[x]=(tr2[x]+v)%P,x+=x&(-x);}
  26. int sum1(int x) {int r=0; while(x) r+=tr1[x],x-=x&(-x); return r;}
  27. int sum2(int x) {int r=0; while(x) r=(r+tr2[x])%P,x-=x&(-x); return r;}
  28. int calc()
  29. {
  30. int res=0;
  31. for(int i=1;i<=n;i++)
  32. {
  33. res=(res+(lint)sum1(n-a[i]+1)*w[a[i]])%P;
  34. res=(res+sum2(n-a[i]+1))%P;
  35. add(n-a[i]+1,w[a[i]]);
  36. }
  37. return res;
  38. }
  39. }
  40. const int N1=2e6;
  41. struct info
  42. {
  43. int c1,s1,c2,s2;
  44. info(int _c1=0,int _s1=0,int _c2=0,int _s2=0) {c1=_c1,s1=_s1,c2=_c2,s2=_s2;};
  45. friend info operator +(info x,info y)
  46. {
  47. int c1=x.c1+y.c1,s1=x.s1+y.s1,c2=x.c2+y.c2,s2=x.s2+y.s2;
  48. return info(c1,s1%P,c2,s2%P);
  49. }
  50. };
  51. namespace inTr
  52. {
  53. int cnt,fa[N1],ch[N1][2],siz[N1]; int val[N1],sum[N1];
  54. inline void update(int p)
  55. {
  56. siz[p]=siz[ch[p][0]]+1+siz[ch[p][1]];
  57. sum[p]=((sum[ch[p][0]]+sum[ch[p][1]])%P+w[val[p]])%P;
  58. }
  59. inline int wh(int p) {return p==ch[fa[p]][1];}
  60. inline void rotate(int p)
  61. {
  62. int q=fa[p],r=fa[q],w=wh(p);
  63. fa[p]=r; if(r) ch[r][wh(q)]=p;
  64. fa[ch[q][w]=ch[p][w^1]]=q;
  65. fa[ch[p][w^1]=q]=p;
  66. update(q),update(p);
  67. }
  68. void splay(int &rt,int p)
  69. {
  70. for(int q=fa[p];q;rotate(p),q=fa[p]) if(fa[q]) rotate(wh(p)^wh(q)?p:q);
  71. update(rt=p);
  72. }
  73. int pre(int rt,int x)
  74. {
  75. int r=0;
  76. for(int p=rt;p;p=ch[p][val[p]<x]) if(val[p]<x) r=p;
  77. return r;
  78. }
  79. void ins(int &rt,int p)
  80. {
  81. if(!rt) {rt=p; return;}
  82. int q=rt;
  83. while(ch[q][val[q]<val[p]]) q=ch[q][val[q]<val[p]];
  84. fa[ch[q][val[q]<val[p]]=p]=q;
  85. update(q); splay(rt,p);
  86. }
  87. int del(int &rt,int x)
  88. {
  89. if(x==0||!rt) return 0;
  90. int p=pre(rt,x+1); if(val[p]!=x) return 0;
  91. splay(rt,p);
  92. int chCnt=(ch[p][0]>0)+(ch[p][1]>0);
  93. if(chCnt==0) {rt=0; return p;}
  94. if(chCnt==1) {rt=ch[p][ch[p][1]>0],fa[rt]=0; return p;}
  95. int q=ch[p][0]; while(ch[q][1]) q=ch[q][1];
  96. splay(rt,q);
  97. fa[ch[q][1]=ch[p][1]]=q;
  98. fa[p]=ch[p][0]=ch[p][1]=0;
  99. update(q);
  100. return p;
  101. }
  102. inline void change(int &rt,int x1,int x2)
  103. {
  104. int p=del(rt,x1); if(!p) p=++cnt;
  105. fa[p]=ch[p][0]=ch[p][1]=0,siz[p]=1;
  106. val[p]=x2,sum[p]=w[x2];
  107. ins(rt,p);
  108. }
  109. info query(int rt,int x)
  110. {
  111. int c1=0,s1=0;
  112. for(int p=rt;p;p=ch[p][val[p]<x])
  113. if(val[p]<x) c1+=siz[p]-siz[ch[p][1]],s1=(s1+sum[p]-sum[ch[p][1]]+P)%P;
  114. return info(c1,s1,siz[rt]-c1,sum[rt]-s1);
  115. }
  116. }
  117. namespace outTr
  118. {
  119. #define Ls (p<<1)
  120. #define Rs (p<<1|1)
  121. int rt[N<<2];
  122. int in(int L,int R,int p1,int p2) {return ((L<=p2&&p2<=R)<<1)|(L<=p1&&p1<=R);}
  123. void change(int p,int L0,int R0,int p1,int p2)
  124. {
  125. int inP=in(L0,R0,p1,p2);
  126. if(inP==1) inTr::change(rt[p],a[p1],a[p2]);
  127. else if(inP==2) inTr::change(rt[p],a[p2],a[p1]);
  128. if(L0==R0) return;
  129. int mid=L0+R0>>1;
  130. if(in(L0,mid,p1,p2)) change(Ls,L0,mid,p1,p2);
  131. if(in(mid+1,R0,p1,p2)) change(Rs,mid+1,R0,p1,p2);
  132. }
  133. int optL,optR;
  134. info query(int p,int L0,int R0,int x)
  135. {
  136. if(optL<=L0&&R0<=optR) return inTr::query(rt[p],x);
  137. int mid=L0+R0>>1; info res=info(0,0,0,0);
  138. if(optL<=mid) res=res+query(Ls,L0,mid,x);
  139. if(mid<optR) res=res+query(Rs,mid+1,R0,x);
  140. return res;
  141. }
  142. }
  143. inline void change(int p1,int p2) {outTr::change(1,1,n,p1,p2);}
  144. inline info query(int L,int R,int x)
  145. {
  146. outTr::optL=L,outTr::optR=R;
  147. return outTr::query(1,1,n,x);
  148. }
  149. int main()
  150. {
  151. n=read(),m=read();
  152. for(int i=1;i<=n;i++)
  153. {
  154. a[0]=read(),w[a[0]]=read();
  155. change(0,i); swap(a[0],a[i]);
  156. }
  157. int ans=init::calc();
  158. for(int i=1;i<=m;i++)
  159. {
  160. int p1=read(),p2=read();
  161. if(p1>p2) swap(p1,p2); else if(p1==p2) {printf("%d\n",ans); continue;}
  162. int x=a[p1],y=a[p2];
  163. info r1=query(p1+1,p2-1,x),r2=query(p1+1,p2-1,y);
  164. ans-=((lint)r1.c1*w[x]%P+r1.s1)%P; ans=(ans+P)%P;
  165. ans+=((lint)r1.c2*w[x]%P+r1.s2)%P; ans=ans%P;
  166. ans+=((lint)r2.c1*w[y]%P+r2.s1)%P; ans=ans%P;
  167. ans-=((lint)r2.c2*w[y]%P+r2.s2)%P; ans=(ans+P)%P;
  168. if(x<y) ans=(ans+w[x]+w[y])%P; else ans=(ans-w[x]-w[y]+P)%P;
  169. printf("%d\n",ans);
  170. change(p1,p2); swap(a[p1],a[p2]);
  171. }
  172. return 0;
  173. }

洛谷P3759 - [TJOI2017]不勤劳的图书管理员的更多相关文章

  1. 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】

    题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...

  2. [P3759][TJOI2017]不勤劳的图书管理员(分块+树状数组)

    题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生 这两本书页数的和的厌烦度.现在有n本被打乱顺序的书 ...

  3. LUOGU P3759 [TJOI2017]不勤劳的图书管理员(树套树)

    传送门 解题思路 和以前做过的一道题有点像,就是区间逆序对之类的问题,用的是\(BIT\)套权值线段树,交换时讨论一下计算答案..跑的不如暴力快.. 代码 #include<iostream&g ...

  4. P3759 [TJOI2017]不勤劳的图书管理员 [树套树]

    树套树是什么啊我不知道/dk 我只知道卡常数w // by Isaunoya #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC o ...

  5. 【bzoj4889】: [Tjoi2017]不勤劳的图书管理员 分块-BIT

    [bzoj4889]: [Tjoi2017]不勤劳的图书管理员 题目大意:给定一个序列(n<=50000),每个数有一个编码ai(ai<=50000)和权值vi(vi<=100000 ...

  6. 【BZOJ4889】[Tjoi2017]不勤劳的图书管理员 分块+树状数组

    [BZOJ4889][Tjoi2017]不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让 ...

  7. 【loj2639】[Tjoi2017]不勤劳的图书管理员

    #2639. 「TJOI2017」不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产 ...

  8. 【洛谷3759】[TJOI2017] 不勤劳的图书管理员(树套树)

    点此看题面 大致题意: 给定一个序列,每个元素有两个属性\(a_i\)和\(v_i\),每次操作改变两个元素的位置,求每次操作后\(\sum{v_i+v_j}[i<j,a_i>a_j]\) ...

  9. 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分

    题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...

随机推荐

  1. 编写Robotium测试程序

    6.编写Robotium测试程序 1)导包 //导入需要测试的工程 import com.example.android.notepad.NotesList; //robotium提供的测试用类 im ...

  2. mongo ServerSelectionTimeoutError: localhost:27017: [Errno 111] Connection refused

    解决方法 rm /var/lib/mongodb/mongod.lock

  3. cdlinux

    xset q xset s 6000 xset -dpms ntpdate time.nist.gov date

  4. 开发工具IDEA环境安装配置

    开发工具IDEA环境安装配置 该工具和eclipse类似,但是使用感受确实比eclipse好,越来越多人开始使用IDEA了. 下载地址如下 : https://www.jetbrains.com/id ...

  5. (50)zabbix API二次开发使用与介绍

    zabbix API开发库 zabbix API请求和响应都是json,并且还提供了各种语法的lib库,http://zabbix.org/wiki/Docs/api/libraries,包含php. ...

  6. (24)zabbix触发器表达式详解

    概述 触发器中的表达式使用很灵活,我们可以创建一个复杂的逻辑测试监控,触发器表达式形式如下:   1 {<server>:<key>.<function>(< ...

  7. GIMP图像窗口的自定义

    具体功能包含:初始缩放比例.空格键按下时触发动作

  8. Vue的响应式规则

    对象属性的响应规则 <body> <div id="root"> {{msg}} </div> </body> <script ...

  9. 如何用纯 CSS 创作一个永动的牛顿摆

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qKmGaJ 可交互视频教 ...

  10. laravel中的gate

    public function boot(){ $this->registerPolicies(); Gate::define('update-post',function($user,$pos ...