LOJ #2734 Luogu P3615 [JOI2016春季合宿]Toilets (结论、贪心)
生活随笔
收集整理的這篇文章主要介紹了
LOJ #2734 Luogu P3615 [JOI2016春季合宿]Toilets (结论、贪心)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
(loj) https://loj.ac/problem/2734
(luogu) https://www.luogu.org/problem/P3615
題解
嗯,考場上肝了\(3h\)然而最后發現一個智障地方沒想到……我果然還是菜的真實啊
首先隊列合法(能在\(N\)分鐘內解決)當且僅當: 每一個長度為偶數的后綴女生數量都不少于一半(一個等價的表述是,如果把男人看成\(1\)女人看成\(-1\)那么任何一個后綴和不大于\(1\), 但是這里由于是對女生操作所以只考慮女生會好很多)。證明只能根據題意一步步推,這里略去。
然后考慮\(O(n)\)做法: 若總共男人數嚴格多于女人數則無解,否則從后往前掃,若某個后綴女人數量少于一半了就把最近的女人移過來,顯然最優。
因此,設從后往前第\(i\)個女人位于從后往前第\(i\)個位置,則答案為\(\max(0,\max_i (b_i-2i))\).
現在字符串長度很大,那么發現對于每一個重復的子串,若其中女人數量多于一半則只需考慮從后往前的第一次重復,否則只需考慮最后一次,于是直接做即可。
時間復雜度\(O(\sum |s_i|)\).
代碼
#include<bits/stdc++.h> #define llong long long #define mkpr make_pair using namespace std;const int N = 2e5; struct Element {vector<char> s;int cnt0,cnt1; llong t; } a[N+3]; llong sum[N+3],sum1[N+3]; char str[N+3]; llong n; int m;int main() {scanf("%lld",&n);scanf("%d",&m);llong tot = 0ll;for(int i=1; i<=m; i++){scanf("%s%lld",str+1,&a[i].t); int len = strlen(str+1);for(int j=1; j<=len; j++){a[i].s.push_back(str[j]);if(str[j]=='F') {tot-=a[i].t; a[i].cnt1++;}else {tot+=a[i].t; a[i].cnt0++;}}}for(int i=m; i>=1; i--){sum[i] = sum[i+1]+a[i].s.size()*a[i].t;sum1[i] = sum1[i+1]+a[i].cnt1*a[i].t;}if(tot>0) {puts("-1"); return 0;}llong ans = 0ll;for(int i=m; i>=1; i--){llong cur1 = sum1[i+1],cur = sum[i+1];if(2*a[i].cnt1<a[i].s.size()){cur1 += a[i].cnt1*(a[i].t-1ll);cur += a[i].s.size()*(a[i].t-1ll);}for(int j=a[i].s.size()-1; j>=0; j--){cur++;if(a[i].s[j]=='F') {cur1++;} // printf("cur=%lld cur1=%lld\n",cur,cur1);ans = max(ans,cur-(cur1<<1)-1);}}printf("%lld\n",ans);return 0; }總結
以上是生活随笔為你收集整理的LOJ #2734 Luogu P3615 [JOI2016春季合宿]Toilets (结论、贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [JOI2012春季合宿]Rotate
- 下一篇: LOJ #2733 [JOI2016春季