A. Yet Another Promotion
题意:买土豆,一种卖a元一公斤,买m公斤送一公斤;一种卖b元一公斤。求买n公斤土豆最少花多少钱。
解:完全没有思考,把a*n, b*n, 买尽可能多m倍数的土豆剩下的都买a和都买b,四种情况堆上去取min。
B. Fedya and Array
题意:令一序列相邻两个元素之差为1(一头一尾也算相邻),如果一个数大于它左右两边,称其为局部最大;小于两边则为最小。现给出所有局部最大之和为x,局部最小之和为y,求任意满足要求的最短序列。
解:画一画大概是一个折线图,观察一下发现所有局部最大之和与局部最大个数没啥关系,再观察一下样例,序列长度为最大最小值相差距离的两倍。那么构造一个序列,其最小值为y,最大值为x,然后两边连起来即可。例如:x=2, y=-1,序列可以是-1, 0, 1, 2, 1, 0.
C. Dora and Search
题意:给出一个排列,求其一个子数组,使得子数组两端都不是该子数组最大值,也不是该子数组最小值。
解:试图枚举每个元素作为左端点,寻找右端点。预处理出每个元素右起第一个大于/小于它的元素位置,这个过程可以用单调栈解决。假设第一个大于它的位置为n,第一个小于它的位置为m,那么我们只能取位置大于等于max(m, n)的元素,才能使得当前元素不是最值。现在考虑判断右端点是否会为最值,同样地预处理出每个元素向左第一个大于/小于它的数的位置,看当前元素是否在这个范围外。乍一看好像是O(n2)的,但介于这是一个排列,如果当前元素是n,每次至少从n+1开始找右端点,所以最多O(nlnn)。最后用stack写的单调栈也跑得飞快,谢谢cf(
代码:
#include <bits/stdc++.h> using namespace std; #define maxx 200005 #define maxn 25 #define maxm 205 #define ll long long #define inf 1000000009 #define mod 2520 int a[maxx]={0}; int biggerleft[maxx]={0}; int biggerright[maxx]={0}; int smallerleft[maxx]={0}; int smallerright[maxx]={0}; stack<int> s; signed main(){ int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } while (!s.empty()) s.pop(); for(int i=1;i<=n;i++){ while(!s.empty() && a[s.top()] >= a[i]) s.pop(); if(!s.empty()) smallerleft[i]=s.top(); else smallerleft[i]=-1; s.push(i); } while (!s.empty()) s.pop(); for(int i=1;i<=n;i++){ while(!s.empty() && a[s.top()] <= a[i]) s.pop(); if(!s.empty()) biggerleft[i]=s.top(); else biggerleft[i]=-1; s.push(i); } while (!s.empty()) s.pop(); for(int i=n;i>=1;i--){ while(!s.empty() && a[s.top()] >= a[i]) s.pop(); if(!s.empty()) smallerright[i]=s.top(); else smallerright[i]=-1; s.push(i); } while (!s.empty()) s.pop(); for(int i=n;i>=1;i--){ while(!s.empty() && a[s.top()] <= a[i]) s.pop(); if(!s.empty()) biggerright[i]=s.top(); else biggerright[i]=-1; s.push(i); } int flag=0; for(int i=1;i<=n;i++){ if(smallerright[i]==-1||biggerright[i]==-1) continue; int r=max(smallerright[i],biggerright[i]); for(int j=r;j<=n;j++){ if(smallerleft[j]==-1||biggerleft[j]==-1) continue; int l=min(smallerleft[j],biggerleft[j]); if(i<=l){ printf("%d %d\n",i,j); flag=1; break; } } if(flag) break; } if(!flag) printf("-1\n"); } return 0; }View Code
D没啥思路,明天补补
标签:maxx,852,int,元素,Codeforces,while,Div,empty,define From: https://www.cnblogs.com/capterlliar/p/17114525.html