\(\\\)

\(Description\)


有\(N\)个人的环,每个人需要至少\(x_i\)种不同的物品,并且要求任意相邻的两人都没有相同的物品,求最少需要多少种物品。

  • \(N\in [0,2\times 10^4]\),\(x_i\in [0,10^5]\)

\(\\\)

\(Solution\ \text O(NlogN)\)


  • 考虑二分答案,首先注意到相邻两人所有物品种类一定不同,所以下界是相邻两人限制之和取\(max\)。

  • 注意到限制只是两两之间的,如果是奇环的话只有头尾会出问题,所以上界最多只需要下界的二倍。

  • 验证的部分就很神仙了,思想是\(min-max\)转化:

    • 设\(mx[i]\)表示在二分总个数为\(x\)的情况下,第\(i\)个位置的人所得物品中,与第一个人相同的个最多有多少个,同理设\(mn[i]\)表示此情况下第\(i\)个位置的人与第一个人最少有多少个相同的物品。

    • 最大部分的转移:考虑要求与前一个不同,所以从第一个人得到的所有物品里去掉前一个最少得到的即可\(\begin{align}mx[i]=min(x[i],x[1]-mn[i-1])\end{align}\)

    • 最小部分的转移:所求即为第一个人得到的所有物品里,去掉当前人最多能够不与第一个人重合的部分,但是还要考虑两人不能重合,所以有\(\begin{align}mn[i]=max(0,a[i]-(x-(a[i-1]-mx[i-1])-a[1]))\end{align}\)具体可以理解成自由部分即为全集去掉第一个人的所有和前一个人的所有,再减掉两个人可行的最大交集。

    • 若最后一个人的最小值可以为\(0\)则证明不会与第一个人冲突,合法。

\(\\\)

\(Code\)


#include<cmath>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 20010
#define R register
#define gc getchar
using namespace std; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} int n,l,r,a[N],mx[N],mn[N]; inline bool valid(int x){
mn[1]=mx[1]=a[1];
for(R int i=2;i<=n;++i){
mx[i]=min(a[i],a[1]-mn[i-1]);
mn[i]=max(0,a[i]-(x-(a[i-1]-mx[i-1])-a[1]));
}
return (mn[n]==0);
} int main(){
n=rd();
for(R int i=1;i<=n;++i) a[i]=rd();
l=a[n]+a[1];
for(R int i=1;i<n;++i) l=max(l,a[i]+a[i+1]);
r=l*2;
while(l<r){
int mid=(l+r)>>1;
valid(mid)?r=mid:l=mid+1;
}
printf("%d\n",l);
return 0;
}

\(\\\)

\(Solution\ \text O(N)\)


这题还有更神仙的做法

  • 首先必须考虑的限制不变,还是两两相邻求和最大值。

  • 考虑另外的限制,即出现奇环时问题的解决方案,此时神仙们怎么就能想到另外一个切入点,每个相同的物品至多只能分给\(\lfloor\frac{N}{2}\rfloor\)个人,因为再多一个人必然会出现相邻的冲突。那么假设\(sum=\sum x_i\),那么\(sum\)这么多的物品中每一类最多只能有\(\lfloor\frac{N}{2}\rfloor\)个有贡献,所以只考虑总和的情况下,至少需要\(\Big\lceil\frac{sum}{\big\lfloor\frac{N}{2}\big\rfloor}\Big\rceil\)种。

  • 对两个角度的答案取最大即可。

\(\\\)

\(Code\)


#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 20010
#define R register
#define gc getchar
using namespace std; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} int n,ans,sum,a[N]; int main(){
n=rd();
for(R int i=1;i<=n;++i) sum+=(a[i]=rd());
ans=max(a[n]+a[1],(int)ceil((double)sum/(n/2)));
for(R int i=1;i<n;++i) ans=max(ans,a[i]+a[i+1]);
printf("%d\n",ans);
return 0;
}

[ ZJOI 2006 ] Trouble的更多相关文章

  1. [ZJOI 2006]超级麻将

    Description Input 第一行一个整数N(N<=100),表示玩了N次超级麻将. 接下来N行,每行100个数a1..a100,描述每次玩牌手中各种牌的数量.ai表示数字为i的牌有ai ...

  2. [ZJOI 2006]书架

    Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...

  3. [ZJOI 2006]物流运输

    Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...

  4. 解题:ZJOI 2006 皇帝的烦恼

    禁止DP,贪心真香 有一个比较明显的贪心思路是让每个人和距离为$2$(隔着一个人)的人尽量用一样的,这样只需要扫一遍然后对每对相邻的人之和取最大值即可.但是当人数为奇数时这样就会出锅,因为最后一个人和 ...

  5. 解题:ZJOI 2006 书架

    题面 学习了如何在维护序列的平衡树上查找某个数:按初始的顺序定个权值,然后每次找那个权值的DFS序即可.具体实现就是不停往上跳,然后是父亲的右儿子就加上父亲的左儿子,剩下的就是继续熟悉无旋树堆 #in ...

  6. 解题:ZJOI 2006 游戏排名系统

    题面 跟i207M学了学重载运算符后找前驱后继,然后就是练练无旋树堆 #include<map> #include<cstdio> #include<string> ...

  7. [BZOJ1003](ZJOI 2006) 物流运输trans

    [题目描述] 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟 ...

  8. 【ZJOI 2006】 物流运输

    [题目链接] 点击打开链接 [算法] 令cost(i,j) = 第i天到第j天走相同的路线,路线长度的最小值 那么,只需筛选出第i天到第j天可以装卸货物的码头,然后将这些码头之间连边,跑弗洛伊德(或其 ...

  9. 洛谷 P2585 [ ZJOI 2006 ] 三色二叉树 —— 树形DP

    题目:https://www.luogu.org/problemnew/show/P2585 首先,三色其实记录两种状态:是绿色,不是绿色 即可,因为红蓝可以随意取反: 一开始因为懒得还原出树,所以写 ...

随机推荐

  1. Leetcode 79.单词搜索

    单词搜索 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单 ...

  2. hdu 5040bfs+优先队列 需要存状态

    /* 剪枝:四秒后状态会变得和原来一样,所以四秒后如果再经过这个点肯定不是最优的舍去 易错点:在一个是从.到.这两个点都没有被照到并且不是摄像机,也可能需要等3秒,因为后面的结果可能再这三秒中发生改变 ...

  3. 武大OJ 612. Catch the sheep

    Description Old Sama is a great and powerful magician in the word. One day, a little girl, Anny, tou ...

  4. 20、Java并发性和多线程-Slipped Conditions

    以下内容转自http://ifeve.com/slipped-conditions/: 所谓Slipped conditions,就是说, 从一个线程检查某一特定条件到该线程操作此条件期间,这个条件已 ...

  5. MyBatis3-实现单表数据的增删查改

    继续前一篇文章http://www.cnblogs.com/EasonJim/p/7050710.html所示的例子,返回的是单个实体,而接下来将进行列表的返回等操作: 一.查询列表 查询出列表,也就 ...

  6. python集合可以进行相减

    python集合可以进行相减 student = {'tom','jim','mary','tom','jack','rose'} print(student) print('rose' in stu ...

  7. ASUS VivoTab RT TF600T忘记系统登录密码,怎么办?

    ASUS VivoTab RT TF600T若忘记系统登录账户密码,可以通过以下两种方式尝试初始化电脑.但是请注意,初始化电脑将删除所有个人文件和应用,并还原电脑设置为默认值. 方法一:通过键盘操作 ...

  8. zTree初体验(一)——小试牛刀

    zTree 是一个依靠 jQuery 实现的多功能 "树插件".优异的性能.灵活的配置.多种功能的组合是 zTree 最大长处. --zTree官网 zTree v3.0 将核心代 ...

  9. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模

    D. The Child and Sequence   At the children's day, the child came to Picks's house, and messed his h ...

  10. IT痴汉的工作现状22-由Dalvik虚拟机引发的口水战

    Dalvik是啥呢? 从未知道冰岛有Dalvik这么一个重要的村庄.直到Dan Bornstein将自己为Android系统编写的进程虚拟机命名为Dalvik后才被我所知. 它是Android系统独有 ...