P3992 [BJOI2017]开车
生活随笔
收集整理的這篇文章主要介紹了
P3992 [BJOI2017]开车
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
P3992 [BJOI2017]開車
題意:
題解:
我們要先將問題轉換
圈是車,x是加油站。紅色部分為車移動的路線
數組a是車數量的前綴和
數組b是加油站的前綴和
而a[i]與b[i]的差的絕對值就是對應的紅色路被走的次數
現在車發生位置移動,b數組沒有影響,a數組i到j這段整體減一
現在我們要做的就是維護a序列,支持區間+1/-1,詢問∑| a[i] - b[i] |
線段樹不能實現
用分塊實現
實現過程:
按照下標分塊,每塊按照a[i] - b[i] 排序
代碼:
代碼為借鑒
#pragma optimize("Ofast") #include<bits/stdc++.h> #define MAXN 150005 #define MAXB 2005 using namespace std; typedef long long ll;int N,B,Q; int a[MAXN], w[MAXN]; map<int,int> mp; map<int,int>::iterator it; map<int,int> id;int q[MAXN][2]; struct Node{int w,val,id,sw;Node(int id=0, ll val=0, int w=0):id(id), val(val), w(w){}bool operator < (const Node& n1) const{return val < n1.val;} }; vector<Node> adj[MAXN]; ll ANS = 0, ans[MAXN], base[MAXN];void rebuild(int id){ANS -= ans[id]; ans[id] = 0;sort(adj[id].begin(), adj[id].end());for(int k=0;k<adj[id].size();k++){ans[id] += abs((ll)adj[id][k].val + base[id]) * adj[id][k].w;if(k==0) adj[id][k].sw = adj[id][k].w;else adj[id][k].sw = adj[id][k-1].sw + adj[id][k].w;}ANS += ans[id]; }void work(int l, int r, int f){int idl = l/B, idr = r/B;if(idl==idr){for(int k=0;k<adj[idl].size();k++){if(l<=adj[idl][k].id && adj[idl][k].id<=r){if(f==0) adj[idl][k].val -= 1;if(f==1) adj[idl][k].val += 1;}}rebuild(idl);}else{if(idl+1<idr){for(int id=idl+1;id<idr;id++){//int lb = 0, rb = adj[id].size()-1, mid;if(f==0){if(adj[id][rb].val + base[id] <= 0){ans[id] += adj[id][rb].sw;ANS += adj[id][rb].sw;base[id] -= 1;continue;}while(lb < rb){mid = (lb + rb)/2;if(adj[id][mid].val + base[id] > 0) rb = mid;else lb = mid + 1;}base[id] -= 1;int p = rb;if(p==0){ans[id] -= adj[id][adj[id].size()-1].sw;ANS -= adj[id][adj[id].size()-1].sw;}else{ans[id] += adj[id][p-1].sw;ANS += adj[id][p-1].sw;ans[id] -= adj[id][adj[id].size()-1].sw - adj[id][p-1].sw;ANS -= adj[id][adj[id].size()-1].sw - adj[id][p-1].sw;}}else{if(adj[id][rb].val + base[id] < 0){ans[id] -= adj[id][rb].sw;ANS -= adj[id][rb].sw;base[id] += 1;continue;}while(lb < rb){mid = (lb + rb)/2;if(adj[id][mid].val + base[id] >= 0) rb = mid;else lb = mid + 1;}base[id] += 1;int p = rb;if(p==0){ans[id] += adj[id][adj[id].size()-1].sw;ANS += adj[id][adj[id].size()-1].sw;}else{ans[id] -= adj[id][p-1].sw;ANS -= adj[id][p-1].sw;ans[id] += adj[id][adj[id].size()-1].sw - adj[id][p-1].sw;ANS += adj[id][adj[id].size()-1].sw - adj[id][p-1].sw;}}}}for(int k=0;k<adj[idl].size();k++){if(l<=adj[idl][k].id && adj[idl][k].id<=r){if(f==0) adj[idl][k].val -= 1;if(f==1) adj[idl][k].val += 1;}}rebuild(idl);for(int k=0;k<adj[idr].size();k++){if(l<=adj[idr][k].id && adj[idr][k].id<=r){if(f==0) adj[idr][k].val -= 1;if(f==1) adj[idr][k].val += 1;}}rebuild(idr);} }int pos[MAXN];int main(){scanf("%d", &N);int x;for(int i=1;i<=N;i++){scanf("%d", &x);pos[i] = x;mp[x] += 1;}for(int i=1;i<=N;i++){scanf("%d", &x);mp[x] -= 1;}scanf("%d", &Q);for(int i=1;i<=Q;i++){scanf("%d%d", &q[i][0], &q[i][1]);if(mp.count(q[i][1])==0) mp[q[i][1]] = 0;}int n = 0, x0 = 0;for(it=mp.begin(); it!=mp.end(); ++it){x = it->first;id[x] = ++n;w[n-1] = x - x0;a[n] = a[n-1] + it->second;x0 = x;}N = n; B = sqrt(N); //cerr<<"B = "<<B<<endl;for(int i=1;i<=N;i++){adj[i/B].push_back(Node(i,a[i],w[i]));}for(int id=0;id<=N/B;++id){rebuild(id);}printf("%lld\n", ANS);int l,r;for(int i=1;i<=Q;i++){l = id[pos[q[i][0]]];r = id[q[i][1]];pos[q[i][0]] = q[i][1];//cerr<<"work "<<l<<" "<<r<<endl;if(l < r) work(l, r-1, 0);if(l > r) work(r, l-1, 1);printf("%lld\n", ANS);}return 0; }總結
以上是生活随笔為你收集整理的P3992 [BJOI2017]开车的全部內容,希望文章能夠幫你解決所遇到的問題。