Task 1 辩论
有N 个参加辩论的候选人,每个人对这两个议题都有明确的态度,支持或反对。
作为组织者,小D 认真研究了每个候选人,并给每个人评估了一个非负的活跃度,他想让活跃度之和尽可能大。选出的候选人必须满足以下两个条件:1. 至少有一半的人支持议题1。2. 至少有一半的人支持议题2。小D 想知道,在满足以上两个条件的情况下,活跃度之和最大是多少。对于$ 100\%$ 的数据,$ N \leq 4 \times 10^5,0 ≤ Ai ≤ 5 \times 10^3 $
Sol : 首先$11$的全部都可以选,然后将$01$ 和 $10$排序,依次选取,把一组最大的$10$和$10$当做$11$处理,
剩余的情况就是$10$或$01$ $00$,这样子显然会让一个数逐渐的趋向于小于Sum/2,所以这个时候直接就挑权值大的数找即可。
复杂度是$O(n \ log_2 \ n)$
# include# define int long longusing namespace std;vector a1,a2,a3,a4,tmp;int n;signed main(){ scanf("%lld",&n); for (int i=1;i<=n;i++) { int op,v; scanf("%lld%lld",&op,&v); if (op==11) a1.push_back(v); else if (op==10) a2.push_back(v); else if (op==01) a3.push_back(v); else if (op==00) a4.push_back(v); } sort(a1.begin(),a1.end()); reverse(a1.begin(),a1.end()); sort(a2.begin(),a2.end()); reverse(a2.begin(),a2.end()); sort(a3.begin(),a3.end()); reverse(a3.begin(),a3.end()); int num=0,ans=0,all=0; for (int i=0;i =all+1) ans+=tmp[i],all++; else break; } printf("%lld\n",ans); return 0; }
Task 2 数独
考虑一个六边形数独,3个方向的每一行都需要填不同的数,并且一个子六边形内部都需要填不同的数。
填写数的值域是$[1,K]$
现在,有一些格子已经填好了数,询问字典序第$n$小的方案,
对于$ 100\%$ 的数据,$k ≤ 31,N ≤ 100000$
Sol : 直接dfs,然后对有关系的点直接存点的编号,由于数的大小为$31$所以可以用二进制数表示填是否填数,
这样就不用开数组模拟了,位运算非常快,然后就基本上没有优化的空间了,本题是一个NP问题。
# pragma GCC optimize(3)# includeusing namespace std;int zu[28][7]={{ 1,2},{ 3,4,5,6,7},{ 8,9,10,11,12,13},{ 14,15,16,17,18},{ 19,20,21,22,23,24},{ 25,26,27,28,29},{ 30,31},{ 7,13},{ 2,6,12,18,24},{ 1,5,11,17,23,29},{ 4,10,16,22,28},{ 3,9,15,21,27,31},{ 8,14,20,26,30},{ 19,25},{ 3,8},{ 1,4,9,14,19},{ 2,5,10,15,20,25},{ 6,11,16,21,26},{ 7,12,17,22,27,30},{ 13,18,23,28,31},{ 24,29},{ 1,2,4,5,6,10,11},{ 3,4,8,9,10,14,15},{ 6,7,11,12,13,17,18},{ 10,11,15,16,17,21,22},{ 14,15,19,20,21,25,26},{ 17,18,22,23,24,28,29},{ 21,22,26,27,28,30,31}};int a[40],n,k;vector v[40]; int get(int pos){ int lim=0; for (int i=1;i 0 && zu[i][k]>0) { for (int k=0;k<7;k++) if (zu[i][j]!=zu[i][k]) v[zu[i][j]].push_back(zu[i][k]); v[zu[i][k]].push_back(zu[i][j]); } } for (int i=1;i<=31;i++) { sort(v[i].begin(),v[i].end()); v[i].erase(unique(v[i].begin(),v[i].end()),v[i].end()); } scanf("%d%d",&k,&n); for (int i=1;i<=31;i++) scanf("%d",&a[i]); dfs(1); puts("No way"); return 0;}