欢迎参观!!==> 博客地址 <== 欢迎参观!!
暑假跑完步会宿舍Div. 2掉分局,开场三道排序题,D题卡到最后乱搞了思路居然AC了。
[你以为你CF过了4题].jpg
结果喜闻乐见的D题被hack掉了,队友同样死亡。
给你n个棍子,要求其中取一些棍子组成梯子,要求满足:
排序取最长的两根棍子作为把手,第二长的棍子确定k,剩下的全拿过来做base。
#include
using namespace std;
#define clr(s) memset(s, 0, sizeof(s))
#define infclr(s) memset(s, 0x3f, sizeof(s))
#define lowclr(s) memset(s, -1, sizeof(s))
#define REP(i, lim) for(int i=0;i
const int inf = 0x3f3f3f3f;
const int MAXN = 1000005;
int len[MAXN];
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
std::ios::sync_with_stdio(false); cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
REP(i, n) cin>>len[i];
sort(len, len+n, greater<int>());
int req = len[1] - 1;
int ans = min(n-2, req);
cout<<max(0, ans)<<endl;
}
return 0;
}
ps: 听说群里有大佬认为题目中告诉你有锤子和钉子是可以把两根木棍拼起来,tql
有 n n n根柱子,对于每根柱子 a i a_i ai都有一个对应半径为 r i r_i ri的碟子放着,你可以移动柱子上的盘子,每次移动要求满足:
题目说明每次当一个柱子空了的时候,都会自动有一个新的盘子(半径与原 r i r_i ri相同)出现。
问你是否有可能将所有种类的盘子放到一个柱子上。
一开始考虑了一下汉诺塔,发现和汉诺塔没什么关系,发现柱子 a a a上的盘子想要移动到柱子b上,a到b的盘子半径就必须是严格递增序列。那么如果想把所有盘子放到一个柱子上,半径最大的盘子两侧必须是严格递减的。
#include
using namespace std;
#define clr(s) memset(s, 0, sizeof(s))
#define infclr(s) memset(s, 0x3f, sizeof(s))
#define lowclr(s) memset(s, -1, sizeof(s))
#define REP(i, lim) for(int i=0;i
const int inf = 0x3f3f3f3f;
const int MAXN = 1000005;
int h[MAXN], test[MAXN];
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
std::ios::sync_with_stdio(false); cin.tie(0);
int n;
cin>>n;
int maxh = -inf;
int index = 0;
REP(i, n){
cin>>h[i];
test[i] = h[i];
if(h[i] > maxh) {
maxh = h[i];
index = i;
}
}
sort(h, h+index);
sort(h+index, h+n, greater<int>());
int f = 1;
REP(i, n) {
if(h[i] != test[i]) f = 0;
}
if(f) cout<<"YES\n";
else cout<<"NO\n";
return 0;
}
给定一串有序数组,要求你分成k段。
每次分割的费用为:
∑ i = 1 k ( m a x ( i ) − m i n ( i ) ) \sum_{i=1}^{k}(max(i)−min(i)) i=1∑k(max(i)−min(i))
求最小花费
共k段,分k-1次,尽可能地将差值大的两个数分开,极为在前 k − 1 k-1 k−1大的差值出,分成 k k k段
#include
using namespace std;
#define clr(s) memset(s, 0, sizeof(s))
#define infclr(s) memset(s, 0x3f, sizeof(s))
#define lowclr(s) memset(s, -1, sizeof(s))
#define REP(i, lim) for(int i=0;i
#define ll long long
const int inf = 0x3f3f3f3f;
const int MAXN = 1000005;
struct Node{
int x, l, r;
}node[MAXN];
bool cmp(Node A, Node B) {
return A.x>B.x;
}
int cut[MAXN];
ll num[MAXN];
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
std::ios::sync_with_stdio(false); cin.tie(0);
int n, k;
cin>>n>>k;
int cnt = 0;
REP(i, n) {
cin>>num[i];
if(i>0) {
node[cnt].x = num[i]-num[i-1];
node[cnt].l = i-1;
node[cnt++].r = i;
}
}
sort(node, node+cnt, cmp);
REP(i, k-1) {
cut[node[i].l] = 1;
}
int now = 0;
ll sum = 0;
REP(i, n) {
if(cut[i] == 1) {
sum+=(num[i]-num[now]);
now = i+1;
}
}
sum+=num[n-1]-num[now];
cout<<sum<<endl;
return 0;
}
给你长度为n的序列,以及两个数值m,k;
子序列的花费为:
∑ i = l r a i − k ⌈ r − l + 1 m ⌉ \sum_{i=l}^{r}a_i-k\lceil \frac{r-l+1}{m} \rceil i=l∑rai−k⌈mr−l+1⌉
求最大花费:
将公式理解为,子序列和,减去子序列长度除m向上取整次数的k。
因为m很小,所以将减k的操作放在数字中,即在固定位置的数字上减去k。
枚举m的模数,在模数对应的位置上减去k,过程中维护最大值。
#include
using namespace std;
#define ll long long
#define ull unsigned long long
#define REP(i, lim) for(int i=0;i
#define REPP(i, lim) for(int i=1;i<=lim;++i)
#define clr(s) memset(s, 0, sizeof(s))
#define lowclr(s) memset(s, -1, sizeof(s))
const int inf = 0x3f3f3f3f;
const int MAXN = 1000055;
int n,m,k;
int a[MAXN],b[MAXN];
ll ans;
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
std::ios::sync_with_stdio(false); cin.tie(0);
scanf("%d%d%d",&n,&m,&k);
REPP(i, n) scanf("%d",a+i);
REP(j, m){
REPP(i, n) b[i]=a[i]-(i%m==j?k:0);
ll s=0;
REPP(i, n){
s=max(s+b[i],0ll);
if(i%m==j)ans=max(ans,s);
}
}printf("%lld\n",ans);
return 0;
}
当天上午多校自闭后,CF被Hack,第二天跟队友约的开封菜早餐也被我