Educational Codeforces Round 55 E. Increasing Frequency(尺取法+思維)
阿新 • • 發佈:2018-12-10
題目連結:
題意:
有一個長度為 n 的序列,已知正整數 c 。可以做一次操作:把區間 [l,r] 的所有數 + k (k為任意整數,l,r也自己定)。問操作後序列中最多有多少個元素的值等於 c 。
思路:
題目所述操作等價於把區間 [l,r] 中的值為 x 的元素都變為 c 。因為 x 的取值範圍為 [1,5e5],所以我們可以列舉 x 的值。
對於每個 x ,用vector(或陣列均可)存序列中值為x的元素的位置(從小到大),然後尺取一遍該vector即可得到對於該 x 能得到的最大結果。對於所有 x,所有vector中的元素之和 = n,所以複雜度為 O(n)。(常數應該會比較大)
如何尺取:
對於 x,如果區間 [st,ed] 中 x 的元素個數大於 c 的元素個數,那麼 ed++;否則,st++;當 ed 超出vector邊界時結束尺取。這裡的st,ed是vector中的下標。
Code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAX = 5e5+10; int n,c; vector<int>mp[MAX]; int num[MAX]; //num[i]為前 i 個數中 c 的個數 int main() { scanf("%d%d",&n,&c); int ans=0; for(int i=1;i<=n;i++){ int x; scanf("%d",&x); if(x==c){ ans++; num[i]=1; } mp[x].push_back(i); } for(int i=2;i<=n;i++){ num[i]+=num[i-1]; } for(int i=1;i<=5e5;i++){ if(i==c) continue; int len = mp[i].size(); if(len==0) continue; //尺取法 int st=0,ed=0; while(ed<len){ if((ed-st+1)>(num[mp[i][ed]]-num[mp[i][st]-1])){ int tmp = (ed-st+1)+num[mp[i][st]-1]+num[n]-num[mp[i][ed]]; ans=max(ans,tmp); ed++; } else{ st++; } } } printf("%d\n",ans); return 0; } /* 10 6 2 6 6 6 2 6 6 2 2 2 */