1. 程式人生 > >4889: [Tjoi2017]不勤勞的圖書管理員 樹套樹

4889: [Tjoi2017]不勤勞的圖書管理員 樹套樹

未來 void 左右 範圍 return 區間求和 val ati mage

國際慣例的題面(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 }
View Code


(另外我為什麽又在刷水題了!)

空に舞う雪はまるで白い花びら ひらひら 風に吹かれて散よ
在茫茫天空飛舞著 好似純白花朵的雪花 迎風飄灑
Ah…染めあげて 消えて無くなるのなら この寂しさも一緒に溶けてゆけ
啊…全都染上純白 如果那些色彩漸漸消失不見的話 那也讓這寂寞溶於一起消失吧

約束を交わす事もなくて 不安が募るばかり
想到相互所約定的那些事情 就會感到越來越不安
ありふれた言葉でもいい 今はただ信じさせて
就算是平常無奇的言語也好 這是如今唯一讓我相信的

この慣れた道も 二人なら幸せ
這條熟悉的道路上 是我們兩人的話 那我會感到幸福的
屆かぬ想いを伝えられたら 未來変わるのかな?
那些無法傳達的思念 若是能夠傳達給你 未來會不會就此發生改變

4889: [Tjoi2017]不勤勞的圖書管理員 樹套樹