constint N =2e5+5;int n, T, a[N];int maxn[N][30], minn[N][30];voidgetST(){for(int i =1; i <= n;++i)
maxn[i][0]= minn[i][0]= a[i];for(int j =1;(1<< j)<= n;++j)for(int i =1; i +(1<< j)-1<= n;++i){
minn[i][j]=min(minn[i][j -1], minn[i +(1<<(j -1))][j -1]);
maxn[i][j]=max(maxn[i][j -1], maxn[i +(1<<(j -1))][j -1]);}}intRMQ(int l,int r,int op){int k =log2(r - l +1);if(op)returnmax(maxn[l][k], maxn[r-(1<<k)+1][k]);elsereturnmin(minn[l][k], minn[r-(1<<k)+1][k]);}int main (){
read (T);while(T --){
cin >> n;for(int i =1; i <= n ; i ++)
scanf ("%d",&a[i]);getST();int mid1 =-1, mid2 =-1;for(int i =1; i <= n -2; i ++){int x =RMQ(1,i,1);int l = i +1, r = n -1, MID;while( r>=l ){
MID = l+r>>1;int two =RMQ(i+1,MID,0);int three =RMQ(MID+1,n,1);if(two < x) r = MID -1;elseif(two > x) l = MID +1;else{if(three < x) r = MID -1;elseif(three > x) l = MID +1;else{ mid1 = i , mid2 = MID ;break;}}}if(mid1 !=-1)break;}if(mid1 !=-1)printf("YES\n%d %d %d\n",mid1,mid2-mid1,n-mid2);elseprintf("NO\n");}}
constint N =2e5+5;int n;int a[N];int buck[N], cnt, val;
unordered_map <int,int> ma;int main (){
CLOSE;
cin >> n;int maxn =0;for(int i =1; i <= n ; i ++){
cin >> a[i];
buck[a[i]]++;if(buck[a[i]]> maxn)
maxn = buck[a[i]], cnt =1, val = a[i];elseif(buck[a[i]]== maxn)
cnt ++;}if(cnt >1)
cout << n << endl;else{int ans =0;for(int i =1; i <=100; i ++){if(i == val)continue;int v =0;
ma.clear();
ma[0]=0;for(int j =1; j <= n ; j ++){if(a[j]== i) v ++;if(a[j]== val) v --;if(!ma.count(v))
ma[v]= j;else
ans =max(ans, j - ma[v]);}}
cout << ans << endl;}}
解题思路:正常来说,是很容易想到
O
(
n
2
k
)
O(n^2k)
O(n2k)的分组背包,可惜时间不够
A
C
AC
AC不得,于是我们观察题目,发现有一个很特殊的点,每个栈是单调栈。那么从网上的结论可知,选择的序列,仅存在一个选不满,然后,用线段树分治的策略搞一搞就好了
constint N =3005;int n , k;int L[N];
vector <ll> sum[N];
ll dp[N], ans =0;void solve (int l ,int r){if(l == r){for(int i =0; i <=min(L[l],k); i ++)
ans = max (ans , dp[k - i]+ sum[l][i]);return;}int mid =(l + r)>>1;
ll cpy[N];for(int i =0; i <= k ; i ++)
cpy[i]= dp[i];for(int i = mid +1; i <= r ; i ++){for(int j = k ; j >= L[i]; j --)
dp[j]= max (dp[j], dp[j-L[i]]+ sum[i][L[i]]);}
solve (l , mid);for(int i =0; i <= k ; i ++)
dp[i]= cpy[i];for(int i = l ; i <= mid ; i ++){for(int j = k ; j >= L[i]; j --)
dp[j]= max (dp[j], dp[j-L[i]]+ sum[i][L[i]]);}
solve (mid +1, r);}int main (){
CLOSE;
cin >> n >> k;for(int i =1; i <= n ; i ++){
cin >> L[i];
sum[i].pb(0);for(int j =1; j <= L[i]; j ++){int x;
cin >> x;
ll p = sum[i][j-1]+ x;
sum[i].pb(p);}}
solve (1, n);
cout << ans << endl;}