国际惯例的题面(Bzoj没有,洛谷找的):
4889: [Tjoi2017]不勤劳的图书管理员 树套树
动态加权逆序对,一眼树套树。
256MB内存,5e4范围,不虚不虚。
首先把交换改成两个插入和两个删除。
考虑插入和删除的贡献,就是统计前面比这个值大的数的数值和,数量和,后面比这个值小的数的数值和,数量和。然后特判一下当前两个值构成逆序对的情况即可(因为这种情况会被计算两遍)。
考虑树状数组套动态开点线段树维护这个东西,线段树只需要单点修改区间求和即可,十分简单。
然而数组开不下啊......理论上我们数组范围要开到2e7左右,然而并跑不满,开到1.4e7就足以AC啦。
(但是跑得奇慢无比,怕不是人傻自带大常数)

代码(话说两个log差不多是根号,我这是两个log还有4倍的常数,大概已经比根号慢了):

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 typedef long long int lli;
 5 const int maxn=5e4+1e2,maxe=1.4e7+1e2;
 6 const int mod=1e9+7;
 7 
 8 int in[maxn],seq[maxn],n;
 9 
10 struct SegmentTree {
11     int lson[maxe],rson[maxe],sum[maxe],siz[maxe],cnt;
12     inline void insert(int &pos,int l,int r,const int &tar,const int &x,const int &d) {
13         if( !pos ) pos = ++cnt;
14         sum[pos] = ( sum[pos] + x ) % mod , siz[pos] += d;
15         if( l == r ) return;
16         const int mid = ( l + r ) >> 1;
17         if( tar <= mid ) insert(lson[pos],l,mid,tar,x,d);
18         else insert(rson[pos],mid+1,r,tar,x,d);
19     }
20     inline int querysum(int pos,int l,int r,const int &ll,const int &rr) {
21         if( !pos || ( ll <= l && r <= rr ) ) return sum[pos];
22         const int mid = ( l + r ) >> 1;
23         if( rr <= mid ) return querysum(lson[pos],l,mid,ll,rr);
24         else if( ll > mid ) return querysum(rson[pos],mid+1,r,ll,rr);
25         return ( querysum(lson[pos],l,mid,ll,rr) + querysum(rson[pos],mid+1,r,ll,rr) ) % mod;
26     }
27     inline int querysiz(int pos,int l,int r,const int &ll,const int &rr) {
28         if( !pos || ( ll <= l && r <= rr ) ) return siz[pos];
29         const int mid = ( l + r ) >> 1;
30         if( rr <= mid ) return querysiz(lson[pos],l,mid,ll,rr);
31         else if( ll > mid ) return querysiz(rson[pos],mid+1,r,ll,rr);
32         return ( querysiz(lson[pos],l,mid,ll,rr) + querysiz(rson[pos],mid+1,r,ll,rr) ) % mod;
33     }
34 }sgt;
35 
36 struct BinaryIndexTree {
37     int root[maxn],id;
38     #define lowbit(x) (x&-x)
39     inline void update(int x,const int &y,const int &val,const int &vs) {
40         while( x <= n ) sgt.insert(root[x],1,n,y,val,vs) , x += lowbit(x);
41     }
42     inline int querysum(int x,const int &ll,const int &rr) {
43         int ret = 0;
44         while(x) ret = ( ret + sgt.querysum(root[x],1,n,ll,rr) ) % mod , x -= lowbit(x);
45         return ret;
46     }
47     inline int querysiz(int x,const int &ll,const int &rr) {
48         int ret = 0;
49         while(x) ret = ( ret + sgt.querysiz(root[x],1,n,ll,rr) ) % mod , x -= lowbit(x);
50         return ret;
51     }
52 }bit;
53 
54 inline int segsum(const int &l,const int &r,const int &ll,const int &rr) {
55     return ( bit.querysum(r,ll,rr) - bit.querysum(l-1,ll,rr) + mod ) % mod;
56 }
57 inline int segsiz(const int &l,const int &r,const int &ll,const int &rr) {
58     return ( bit.querysiz(r,ll,rr) - bit.querysiz(l-1,ll,rr) + mod ) % mod;
59 }
60 
61 
62 int main() {
63     static int m;
64     static lli now;
65     scanf("%d%d",&n,&m);
66     for(int i=1;i<=n;i++) scanf("%d",seq+i) , scanf("%d",in+seq[i]);
67     for(int i=1;i<=n;i++) {
68         now = ( now + bit.querysum(i,seq[i]+1,n) ) % mod , now = ( now + (lli) bit.querysiz(i,seq[i]+1,n) * in[seq[i]] % mod ) % mod;
69         bit.update(i,seq[i],in[seq[i]],1);
70     }
71     for(int i=1,a,b;i<=m;i++) {
72         scanf("%d%d",&a,&b);
73         if( a > b ) std::swap(a,b);
74         if( a == b ) {
75             printf("%lld\n",now);
76             continue;
77         }
78         now -= segsum(1,a-1,seq[a]+1,n) + segsum(a+1,n,1,seq[a]-1) , now -= (lli) in[seq[a]] * ( segsiz(1,a-1,seq[a]+1,n) + segsiz(a+1,n,1,seq[a]-1) ) % mod , now = ( now % mod + mod ) % mod;
79         now -= segsum(1,b-1,seq[b]+1,n) + segsum(b+1,n,1,seq[b]-1) , now -= (lli) in[seq[b]] * ( segsiz(1,b-1,seq[b]+1,n) + segsiz(b+1,n,1,seq[b]-1) ) % mod , now = ( now % mod + mod ) % mod;
80         bit.update(b,seq[b],mod-in[seq[b]],-1) , bit.update(a,seq[a],mod-in[seq[a]],-1);
81         if( seq[a] > seq[b] ) now = ( now + in[seq[a]] + in[seq[b]] ) % mod; // it have been subed two times .
82         std::swap(seq[a],seq[b]);
83         bit.update(a,seq[a],in[seq[a]],1) , bit.update(b,seq[b],in[seq[b]],1);
84         now += segsum(1,a-1,seq[a]+1,n) + segsum(a+1,n,1,seq[a]-1) , now += (lli) in[seq[a]] * ( segsiz(1,a-1,seq[a]+1,n) + segsiz(a+1,n,1,seq[a]-1) ) % mod , now = ( now % mod + mod ) % mod;
85         now += segsum(1,b-1,seq[b]+1,n) + segsum(b+1,n,1,seq[b]-1) , now += (lli) in[seq[b]] * ( segsiz(1,b-1,seq[b]+1,n) + segsiz(b+1,n,1,seq[b]-1) ) % mod , now = ( now % mod + mod ) % mod;
86         if( seq[a] > seq[b] ) now = ( now - in[seq[a]] - in[seq[b]] + mod ) % mod; // it have been added two times .
87         printf("%lld\n",now);
88     }
89     return 0;
90 }
View Code

相关文章:

  • 2021-10-17
  • 2022-01-25
  • 2022-12-23
  • 2022-12-23
  • 2021-11-24
  • 2021-06-06
  • 2021-09-18
  • 2022-12-23
猜你喜欢
  • 2022-01-02
  • 2021-07-26
  • 2022-12-23
  • 2021-11-05
  • 2022-12-23
  • 2021-07-24
  • 2021-05-16
相关资源
相似解决方案