首页 > 其他分享 >题解 P6831 - [IOI2020] 嘉年华奖券

题解 P6831 - [IOI2020] 嘉年华奖券

时间:2023-08-07 12:33:06浏览次数:44  
标签:系数 int 题解 IOI2020 MAXN dfrac 奖券 id

小清新 IOI 题。

首先考虑怎么求出答案。等价于我选择 \(\dfrac{nk}{2}\) 个数令它们系数为 \(1\),再选 \(\dfrac{nk}{2}\) 个数令它们系数为 \(-1\),最大化每个数的值乘以系数之和,并且要求每个奖券选择的数的个数恰好是 \(k\) 个。

考虑先令每个奖券的前 \(k\) 个数系数为 \(-1\),然后再将 \(\dfrac{nk}{2}\) 个数改成正数。因为每次我显然是选择一个奖券,将最靠右的负数去掉,再选择最靠左的没有选择的数作为正数,而你发现这个贡献是凸的,所以优先队列维护即可。时间复杂度 \(O(nm\log n)\)。

最后考虑怎么构造方案。直接每次选择剩余负数最多的 \(\dfrac{n}{2}\) 个奖券填上 \(-1\),另外 \(\dfrac{n}{2}\) 个奖券填上 \(+1\) 即可。你可能会担心如果这 \(n\) 个奖券的 \(\pm 1\) 的系数不符合我们构造出来的系数怎么办,不过仔细想想不会出现这样的情况。因为我们选择的最大的负数肯定不会超过最小的正数,否则我们一定可以交换这两个数的系数使得答案变得更优,于是 \(\pm 1\) 的系数一定是对的,直接 xjb 取即可。

const int MAXN=1500;
int n,m,pt[MAXN+5],coef[MAXN+5][MAXN+5],L[MAXN+5],R[MAXN+5];
ll find_maximum(int k,vector<vector<int> >x){
	n=x.size();m=x[0].size();int cnt=n*k/2;
	for(int i=0;i<n;i++)for(int j=0;j<k;j++)coef[i][j]=-1;
	for(int i=0;i<n;i++)pt[i]=k-1;
	priority_queue<pii>q;
	for(int i=0;i<n;i++)q.push(mp(x[i][m-1]+x[i][k-1],i));
	while(cnt--){
		pii p=q.top();q.pop();int id=p.se;
		coef[id][pt[id]]=0;coef[id][pt[id]+m-k]=1;--pt[id];
		if(pt[id]>=0)q.push(mp(x[id][pt[id]+m-k]+x[id][pt[id]],id));
	}
	ll res=0;
	for(int i=0;i<n;i++)for(int j=0;j<m;j++)res+=coef[i][j]*x[i][j];
	vector<vector<int> >ans;ans.resize(n);
	for(int i=0;i<n;i++)ans[i].resize(m);
	for(int i=0;i<n;i++)L[i]=pt[i],R[i]=pt[i]+m-k+1;
	for(int i=0;i<n;i++)for(int j=0;j<m;j++)ans[i][j]=-1;
	for(int i=0;i<k;i++){
		static int ord[MAXN+5];
		for(int j=0;j<n;j++)ord[j]=j;
		sort(ord,ord+n,[&](int x,int y){return L[x]>L[y];});
		for(int j=0;j<n/2;j++)ans[ord[j]][L[ord[j]]]=i,--L[ord[j]];
		for(int j=n/2;j<n;j++)ans[ord[j]][R[ord[j]]]=i,++R[ord[j]];
	}
	allocate_tickets(ans);
	return res;
}

标签:系数,int,题解,IOI2020,MAXN,dfrac,奖券,id
From: https://www.cnblogs.com/tzcwk/p/luogu-P6831.html

相关文章

  • HHKB2020 D 题解
    problem&blog。特判一下\(a+b>n\)时为\(0\)。正难则反,计算重叠的方案数。重叠即\(x,y\)轴均有交集,于是转化为两条线段相交的方案数(两条线段认为是不同的)。正难则反,计算不相交的方案数。第一条线段有\((n-b+1)-a+1=n-a-b+2\)种可能,第二条有\((n-a-b+1)\)种可能,故方案......
  • 题解 [POI2012] OKR-A Horrible Poem
    题目链接询问循环节的“模板题”?首先,有一个经典结论:若存在一长度为\(len\)的循环节,则\(s[l\simr-len]=s[l+len\simr]\),简单来说就是利用移位,说明是否是循环节。有了这个结论,再使用字符串哈希,我们就可以做到\(O(1)\)判断。因为:字符串长度=循环节长度\(\times\)循环......
  • [国家集训队] Tree II 题解报告
    [国家集训队]TreeII一道·真·板子·题就是练习LCT懒标记的题目除了翻转标记以外还要维护乘法标记和加法标记注意加法标记和乘法标记的维护!!!加法标记因为splay的区间大小不是固定的,所以我们要维护size,并且子树的sum要加上size乘上标记其他的就只用直接加上即可voidpusha......
  • 题解 P8085 [COCI2011-2012#4] KRIPTOGRAM
    题目链接题目问的是相对位置是否一样,即若\(s\)的第\(1,2,3\)个字符串相等,\(t\)的第\(1,2,3\)个字符串也相等,则\(s=t\)。由于\(t\)的长度是固定的,所以我们使用哈希进行快速匹配。那么如何设计哈希函数则成为本题的难点。由于问相对位置,那么可以记\(val[i]\)表示......
  • 『MGOI』Simple Round I | B. 魔法照相馆 题解
    题目传送门一道模拟题。并不复杂的模拟题,也不需要用到贪心。我们可以创建一个数组来记录每个幕布是否被拉上,统计答案的时候,就看看这块幕布前面有多少个没拉上的,最后如果这块幕布拉上了,就重新放下来就行了。#include<bits/stdc++.h>#definelllonglong#defineINF1e9usi......
  • 【题解】Codeforces Round 890(CF1856)
    赛时过了A-E1,rk195可惜是E2傻逼了不会背包优化了,直接连普及组水平都不到了。A.TalesofaSort题目描述:给定长度为\(n\)的序列\(a\),每次操作为对于所有\(i\)将\(a_i\)变为\(\max(a_i-1,0)\),询问最少多少次操作之后可以让序列\(a\)单调不降。题目分析:唯一能改变......
  • 【题解】Luogu[P9504] 『MGOI』Simple Round I C. 魔法禁林
    Link这题我们发现如果直接去枚举生命和法力值显然是不行的,又看到说最小的生命值,不禁想到最短路,但是怎么跑?我们令经过一条边之前魔力值为\(k\),那么该边的边权为\(\lfloor\dfrac{w}{k}\rfloor\),于是我们讲题目转化为了边权为\(\lfloor\dfrac{w}{k}\rfloor\)时\(s\)到\(t\)......
  • [ABC310] D~F 题解
    [ABC310]D~F题解D-PeacefulTeams暴力搜索,搜索每个人在的队伍,为了去重,在一个人第一次加入新的队伍之后跳出。bitset<N>st;voiddfs(intu){for(inti=1;i<=m;i++)if(pos[a[i]]&&pos[b[i]]&&pos[a[i]]==pos[b[i]])return;if(u>n)......
  • C++动态规划经典试题解析之打家劫舍系列
    1.前言力扣上有几道与打家劫舍相关的题目,算是学习动态规划时常被提及的经典试题,很有代表性,常在因内大大小小的社区内看到众人对此类问题的讨论。学习最好的方式便是归纳总结、借鉴消化,基于这个目的,本文对此类问题也做了讲解,在一些优秀思想的基础上添加了个人观点。闲话少说,进入......
  • P9499 「RiOI-2」change 题解--zhengjun
    思维妙妙题。赛时的错误做法:找到每个点往后进位变优的位置,最多\(O(\log)\)个;然后从前往后能变优就变优,往后贪心进位。hack数据:0133510021022输出:100这样子由于\(1\)到\(2\)不优,而\(1\)到\(3\)个数不够,所以导致无法进位到\(3\)。所以加强一下......