日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

CSP认证201809-4再卖菜[C++题解]:差分约束、前缀和

發布時間:2025/4/5 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CSP认证201809-4再卖菜[C++题解]:差分约束、前缀和 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 題目解答
      • 題目鏈接

題目解答


來源:acwing

分析:

對于a0,a1,...,ana_0, a_1,...,a_na0?,a1?,...,an?,經過計算相鄰的數的平均值得到b0,b1,...,bnb_0, b_1,...,b_nb0?,b1?,...,bn?,現在給定序列b的值,反求序列a的值。

為了處理3者求和,我們使用前綴和的技巧求三個數或者2個數的和: ai?1+ai+ai+1=s[i+1]?s[i?2]a_{i-1}+a_i+a_{i+1} = s[i+1] - s[i-2]ai?1?+ai?+ai+1?=s[i+1]?s[i?2]

其實,bi=?ai?1+ai+ai+13?=?s[i+1]?s[i?2]3?b_i = \lfloor \frac{a_{i-1}+a_i+a_{i+1}}{3}\rfloor= \lfloor \frac{s[i+1] - s[i-2]}{3}\rfloorbi?=?3ai?1?+ai?+ai+1???=?3s[i+1]?s[i?2]??
等價于 3bi≤s[i+1]?s[i?2]≤3bi+2(1)3b_i \leq s[i+1] - s[i-2] \leq 3b_i +2 (1)3bi?s[i+1]?s[i?2]3bi?+2(1)

由于題目給定每個店鋪的價格都是正整數
所以還有約束:s[i]?s[i?1]≥1(2)s[i] - s[i-1] \geq 1(2)s[i]?s[i?1]12

得到了不等式約束,并且都是作差的形式,所以這是一道差分約束的題目。那么就要往spfa求最短路和最長路的角度去想。這里要求字典序最小的值,按照套路,這里要用最長路,所以三角不等式為:
dist[b]≥dist[a]+cdist[b] \geq dist[a] + cdist[b]dist[a]+c

對應的是a到b有一條權值為c的邊。

所以我們對上面的(1)和(2)不等式約束進行變形,同時得到點、邊權的關系:

(1)式可以拆成2個不等式:
s[i+1]≥s[i?2]+3bis[i+1] \geq s[i-2] + 3b_is[i+1]s[i?2]+3bi?

對應的是i-2這個點到i+1這個點有一條權值為3bi3b_i3bi?的邊
s[i?2]≥s[i+1]?(3bi+2)s[i-2] \geq s[i+1] -(3b_i + 2)s[i?2]s[i+1]?(3bi?+2)
對應的是i+1這個點到i-2這個點有一條權值為?(3bi+2)-(3b_i+2)?3bi?+2的邊

(2)式對應不等式:
s[i]≥s[i?1]+1s[i] \geq s[i-1] + 1 s[i]s[i?1]+1

對應的是i-1這個點到i這個點有一條權值為111的邊

關于差分約束的板子
算法提高課-圖論-差分約束- AcWing 1169. 糖果:spfa求單源最短路、差分約束

這里的最長路指的是,建立一個超級源點0號點,求出所有點到0號點的最長路,為啥求出最長路之后就是我們要求的值呢? 因為這里本質上求的是一系列不等式:
s[i]≥...≥s[0]≥0s[i] \geq... \geq s[0] \geq 0s[i]...s[0]0很多這樣的不等式,我們取它們的交集即可。

每一個這樣的不等式鏈路對應圖中的一個最短路(或者最長路),這里是因為求的是最小值,用的是最長路。

ac代碼

#include<bits/stdc++.h> using namespace std; const int N = 310, M = N * 3; int n, m; int h[N], e[M],w[M], ne[M], idx; int dist[N], q[N]; int b[N]; bool st[N];void add(int a, int b, int c){e[idx] = b, w[idx] =c, ne[idx] = h[a], h[a] = idx ++; }// SPFA求最長路 void spfa(){// 求最長路,需要初始化為-∞memset(dist,-0x3f, sizeof dist);queue<int> q;q.push(0);dist[0] = 0;while(q.size()){auto t = q.front();q.pop();st[t] = false;for(int i = h[t]; ~i; i = ne[i]){int j = e[i];if(dist[j] < dist[t] + w[i]){dist[j] = dist[t] + w[i];if(!st[j]){q.push(j);st[j] = true;}}}} }int main(){memset(h, -1, sizeof h);cin >> n;for(int i = 1; i <= n; i ++) cin >> b[i];//除去端點值需要滿足的條件for(int i = 2; i < n; i ++){add(i -2, i + 1, b[i] * 3 );add( i + 1, i - 2, -(b[i] * 3 + 2));}//端點需要滿足的條件add(0, 2, b[1] * 2), add(2, 0, -(b[1] * 2 + 1));add(n - 2, n, b[n] * 2), add(n, n - 2, -(b[n] * 2 +1));// 所有點都滿足的條件for(int i = 1; i <= n; i ++) add(i - 1, i, 1);// 求最長路spfa();for(int i = 1; i <= n; i ++)// 前綴和求某點的值cout << dist[i] - dist[i - 1] << " ";}

題目鏈接

https://www.acwing.com/problem/content/3268/

總結

以上是生活随笔為你收集整理的CSP认证201809-4再卖菜[C++题解]:差分约束、前缀和的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。