国际惯例的题面(Bzoj没有,洛谷找的):
动态加权逆序对,一眼树套树。
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 }
(另外我为什么又在刷水题了!)
空に舞う雪はまるで白い花びら ひらひら 風に吹かれて散よ
在茫茫天空飞舞着 好似纯白花朵的雪花 迎风飘洒
Ah…染めあげて 消えて無くなるのなら この寂しさも一緒に溶けてゆけ
啊…全都染上純白 如果那些色彩渐渐消失不见的话 那也让这寂寞溶于一起消失吧
約束を交わす事もなくて 不安が募るばかり
想到相互所约定的那些事情 就会感到越来越不安
ありふれた言葉でもいい 今はただ信じさせて
就算是平常无奇的言语也好 这是如今唯一让我相信的
この慣れた道も 二人なら幸せ
这条熟悉的道路上 是我们两人的话 那我会感到幸福的
届かぬ想いを伝えられたら 未来変わるのかな?
那些无法传达的思念 若是能够传达给你 未来会不会就此发生改变
原文地址:https://www.cnblogs.com/Cmd2001/p/8947552.html
时间: 2024-10-05 06:49:50