上海理工大学第二届“联想杯”全国程序设计邀请赛 Identical Day 思维 + 暴力
傳送門
文章目錄
- 題意:
- 思路:
題意:
給你一個010101序列,假設有一段長為lll連續的全111子串,定義這段字串不高興值為l?(l+1)2\frac{l*(l+1)}{2}2l?(l+1)?,整個串的所有不高興值相加為總的不高興值。現在你可以將某個111變成000,問最少多少次操作可以使得總不高興值≤k\le k≤k。
思路:
由于比賽的時候被好幾個題卡著,導致分析復雜度分析錯了,錯過接近正解的機會。
首先一上來就寫了個貪心,每次找最大的那個讓后從中間斷開。這個其實挺容易就hackhackhack掉了,比如111111111111111這個序列,如果按照上面的操作兩次之后變成100111001110011,顯然比101011010110101大,所以這個貪心策略是錯誤的,但是我們還是可以從中發現一些東西。
假設我們要將lll分成xxx段,那么一定是均分這一段,這個東西是可以O(1)O(1)O(1)算出來的,這個時候我們可以枚舉每段,讓后再枚舉將其分割成xxx段,向優先隊列里面加入與分割成x?1x-1x?1段差的絕對值,明顯這個值是遞減的。之后就從優先隊列中不斷的拿出來,將總值減去,一直到sum≤ksum\le ksum≤k即可,這樣一定是最優的。
上面枚舉分割段的復雜度是O(n)O(n)O(n)的,腦子抽了一度以為能卡成O(n2)O(n^2)O(n2)的。
// Problem: Identical Day // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/17574/I // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #include<random> #include<cassert> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid ((tr[u].l+tr[u].r)>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f; const double eps=1e-6;int n; LL k; int a[N]; vector<int>v;LL get(int len,int x) {int rest=len-x;x++;LL one=rest/x,re=rest%x;return one*(one+1)/2*(x-re)+(one+1)*(one+2)/2*re; }int main() { // ios::sync_with_stdio(false); // cin.tie(0);cin>>n>>k;for(int i=1;i<=n;i++) scanf("%1d",&a[i]);LL sum=0;priority_queue<LL>q;for(int i=1;i<=n;i++) {if(a[i]==0) continue;LL cnt=0;while(a[i]==1&&i<=n) i++,cnt++;i--;sum+=1ll*cnt*(cnt+1)/2;v.pb(cnt);}for(auto x:v) {LL pre=1ll*x*(x+1)/2;for(int i=1;i<=x;i++) {LL now=get(x,i);//cout<<x<<' '<<i<<' '<<now<<endl;q.push(pre-now);pre=now;}}int ans=0;while(sum>k) {sum-=q.top(); q.pop();ans++;}cout<<ans<<endl;return 0; } /**/總結
以上是生活随笔為你收集整理的上海理工大学第二届“联想杯”全国程序设计邀请赛 Identical Day 思维 + 暴力的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 心口疼的快速缓解办法
- 下一篇: 脑立清治什么病