Educational Codeforces Round 91 (Rated for Div. 2) D.Berserk And Fireball(思维,暴力破解,分情况)
題目傳送
題意:
現在有一個排列,再給出一個刪除后的數組,刪除操作只有倆種:一種是,選擇連續的k個數,刪除,消耗x點代價。另一種是,選擇連續的倆個數,刪除其中小的數,消耗y點代價。現在問,能否得到刪除后的數組,如果不能輸出-1,如果能,請打出最小代價。
思路:
很明顯就是分情況操作,先記錄下,每個數的位置,然后在刪除后的數組中對應起來,看刪除的哪些數,枚舉刪除的數的最大值(這里要注意,因為區間不會重復,所以我們暴力枚舉最大值,最壞也就總共2e5次操作),再看刪除的這些數是否滿足刪除條件。
1.如果y*k大于等于x,那么肯定是代價最小的(每次選擇連續的倆個數),但是我們要觀察是否滿足刪除條件,條件:左端點,或者右端點的值要大于這之間的最值
**(1)**如果滿足這個條件,那么直接刪用y代價,刪除端點中間的數即可
(2)如果不滿足,那么我們要看是否大于k,如果大于了k,我們就可以用y的代價刪除這個最值,而在這之間,我們可以利用這個最值去刪除其他數(不用管這個過程,我們只知道留下最值即可),所以代價消耗是x + (中間要刪除的個數-k)*y。
如果都不滿足這個條件,那么說明這個數最大值是刪不了的,所以輸出-1
2.如果y*k > x,那么我們就要盡量的用x的代價去刪除數。條件;刪除的數的個數大于等于k
(1)如果滿足條件,那么代價為(個數/k)*x + (個數%k)*y
(2)如果不滿足條件,那么沒辦法,我們只能用y的代價去刪,那么回到1中所述,尋找最值,如果滿足條件就刪,不滿足退出輸出-1
AC代碼
#include <bits/stdc++.h> inline long long read(){char c = getchar();long long x = 0,s = 1; while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();} while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();} return x*s;} using namespace std; #define NewNode (TreeNode *)malloc(sizeof(TreeNode)) #define Mem(a,b) memset(a,b,sizeof(a)) #define lowbit(x) (x)&(-x) const int N = 2e5 + 10; const long long INFINF = 0x7f7f7f7f7f7f7f; const int INF = 0x3f3f3f3f; const double EPS = 1e-7; const int mod = 1e9+7; const double II = acos(-1); const double PP = (II*1.0)/(180.00); typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> piil; ll arr[N],ans[N],vis[N]; ll solve(ll l,ll r) {ll Max = 0;for(ll i = l+1;i < r;i++)Max = max(Max,arr[i]);return Max; }//枚舉最大值 signed main() {std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);// freopen("input.txt","r",stdin);// freopen("output.txt","w",stdout);ll n,m,x,k,y,a = 2,sum = 0,flag = 0,flag1 = 0;cin >> n >> m >> x >> k >> y;for(ll i = 1;i <= n;i++) {cin >> arr[i];vis[arr[i]] = i;}//記錄位置for(ll i = 1;i <= m;i++) cin >> ans[i];if(ans[1] != arr[1]) a--,ans[0] = arr[1];//這里如果ans[1] != arr[1],說明前面還刪了數,還得加個端點進去if(ans[m] != arr[n]) ans[++m] = arr[n],flag1 = 1;//與上面同理for(ll i = a;i <= m;i++){ll l = vis[ans[i-1]],r = vis[ans[i]];//端點位置ll num = r-l-1;//中間要刪除的個數ll Max = solve(l,r);if(i == 1) num++,Max = max(Max,arr[l]);//這里注意,如果在上面我們添加了端點進去,那么這個端點其實也是要刪的,所以需要更新信息if(i == m && flag1) num++,Max = max(Max,arr[r]);//與上同理if(num < 0) {flag = 1;break;}//如果位序發生了改變,那么不可能if(y*k <= x && (Max < arr[l] || Max < arr[r]))//分情況sum += y*num;else if(y*k <= x && num >= k)sum += (x + (num-k)*y);else if(y*k > x && num >= k)sum += (num/k*x + (num%k)*y);else if(num < k && (Max < arr[l] || Max < arr[r]))sum += y*num;else{flag = 1;break;}}if(flag) cout << -1 << endl;else cout << sum << endl; }總結
以上是生活随笔為你收集整理的Educational Codeforces Round 91 (Rated for Div. 2) D.Berserk And Fireball(思维,暴力破解,分情况)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: admob 服务器验证_Admob广告植
- 下一篇: 假龙吟歌 - 李贺