bzoj 4069~4071 APIO2015
T1
从高到底按位确定答案
A=1时f[i]表示前i个数合法的划分至少需要分出几段,时间复杂度$O(n^2log(ans))$
A>1时f[i][j]表示前i个数划分为j段是否可能合法,转移显然,时间复杂度$O(n^3log(ans)/32)$
#include<cstdio>
#include<cstring>
#include<bitset>
typedef long long i64;
int n,A,B;
int f[];
i64 s[],ans=;
std::bitset<>d[];
int main(){
scanf("%d%d%d",&n,&A,&B);
for(int i=;i<=n;++i)scanf("%lld",s+i),s[i]+=s[i-];
if(A==){
for(int x=;x>=;--x){
i64 v=ans|((1ll<<x)-);
for(int i=;i<=n;++i){
f[i]=0x3f3f3f3f;
for(int j=;j<i;++j)if(((s[i]-s[j])|v)==v&&f[j]+<f[i])f[i]=f[j]+;
}
if(f[n]>B)ans|=1ll<<x;
}
}else{
d[][]=;
for(int x=;x>=;--x){
i64 v=ans|((1ll<<x)-);
for(int i=;i<=n;++i){
d[i].reset();
for(int j=;j<i;++j)if(((s[i]-s[j])|v)==v)
d[i]|=d[j]<<;
}
bool dd=;
for(int i=A;i<=B;++i)dd|=d[n][i];
if(!dd)ans|=1ll<<x;
}
}
printf("%lld\n",ans);
return ;
}
T2
对每个不同的(p[i],b[i]%p[i]),新建一些点表示这个i可以走到的位置,每个位置和每个i也建出对应的点
最后可以转为01边权最短路
可以证明时空复杂度均为$O(n^\frac 3 2)$
#include<bits/stdc++.h>
const int inf=0x3f3f3f3f,C=;
int n,m,b[],p[],B;
struct edge{
int to;
edge*nx;
}*ep=,*mep=;
edge*e0[*C];
int l[*C];
bool is[*C];
void ae(int a,int b){
if(ep==mep)ep=new edge[],mep=ep+;
*ep=(edge){b,e0[a]};
e0[a]=ep++;
}
int idp;
struct node{int w,l;void upd1(int);};
std::deque<node>q;
std::map<int,int>mp;
void node::upd1(int u){
if(::l[u]>l+)q.push_back((node){u,::l[u]=l+});
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<m;++i)scanf("%d%d",b+i,p+i);
idp=n+m;
for(int i=;i<m;++i){
ae(b[i],n+i);
ae(n+i,b[i]);
int x=p[i],y=b[i]%x;
int&z=mp[x<<|y];
if(!z){
z=idp;
int a;
for(a=y;a+x<n;a+=x){
is[idp]=;
ae(idp++,a);
}
ae(idp++,a);
}
ae(n+i,z+(b[i]-y)/x);
}
std::fill(l,l+idp+,inf);
q.push_back((node){n,l[n]=});
while(!q.empty()){
node w=q.front();q.pop_front();
if(w.l!=l[w.w])continue;
if(w.w==n+)return printf("%d\n",w.l),;
for(edge*i=e0[w.w];i;i=i->nx){
int u=i->to;
if(l[u]>w.l)q.push_front((node){u,l[u]=w.l});
}
if(is[w.w-])w.upd1(w.w-);
if(is[w.w])w.upd1(w.w+);
}
return puts("-1"),;
}
T3
对同侧的直接计算贡献,否则考虑不同侧的
K=1,中位数位置最优
K=2,可以证明按$S_i+T_i$排序后划分成左右两部分后按K=1的情况处理,能找到最优解
带插入的中位数可以用对顶堆维护
时间复杂度$O(nlogn)$
#include<bits/stdc++.h>
typedef long long i64;
int k,n;
char s1[],s2[];
int p1,p2,xs[],xp=;
i64 ans=;
int abs(int x){return x>?x:-x;}
struct pos{
int a,b;
bool operator<(pos w)const{return a+b<w.a+w.b;}
}ps[];
int pp=;
i64 ss1=,ss2=,f[];
std::priority_queue<int>q1;
std::priority_queue<int,std::vector<int>,std::greater<int> >q2;
void init(){
q1=std::priority_queue<int>();
q2=std::priority_queue<int,std::vector<int>,std::greater<int> >();
ss1=ss2=;
}
void ins(int x){
if(q1.size()&&x<=q1.top()){
q1.push(x),ss1+=x;
if(q1.size()>q2.size()+){
int x=q1.top();q1.pop();
ss1-=x;ss2+=x;
q2.push(x);
}
}else{
q2.push(x),ss2+=x;
if(q2.size()>q1.size()+){
int x=q2.top();q2.pop();
ss2-=x;ss1+=x;
q1.push(x);
}
}
}
void mins(i64&a,i64 b){if(a>b)a=b;}
i64 cal(){
return ss2-ss1;
}
int main(){
scanf("%d%d",&k,&n);
if(k==){
for(int t=;t<n;++t){
scanf("%s%d%s%d",s1,&p1,s2,&p2);
if(s1[]==s2[])ans+=abs(p2-p1);
else ++ans,xs[xp++]=p1,xs[xp++]=p2;
}
if(xp){
std::nth_element(xs,xs+xp/,xs+xp);
int x=xs[xp/];
for(int a=;a<xp;++a)ans+=abs(xs[a]-x);
}
}else{
for(int t=;t<n;++t){
scanf("%s%d%s%d",s1,&p1,s2,&p2);
if(s1[]==s2[])ans+=abs(p2-p1);
else ++ans,ps[pp++]=(pos){p1,p2};
}
std::sort(ps,ps+pp);
if(pp){
init();
for(int a=;a<pp;++a){
ins(ps[a].a);ins(ps[a].b);
f[a]=cal();
}
i64 mx=f[pp-];
init();
for(int a=pp-;a;--a){
ins(ps[a].a);ins(ps[a].b);
mins(mx,cal()+f[a-]);
}
ans+=mx;
}
}
printf("%lld\n",ans);
return ;
}
bzoj 4069~4071 APIO2015的更多相关文章
- bzoj 4069 [Apio2015]巴厘岛的雕塑 dp
[Apio2015]巴厘岛的雕塑 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 494 Solved: 238[Submit][Status][Dis ...
- BZOJ 4069 [Apio2015]巴厘岛的雕塑 ——贪心
自己首先想了一种方法$f(i)$表示前$i$个最小值为多少. 然而发现位运算并不满足局部最优性. 然后我们可以从高到低贪心的判断,使得每一组的和在一个特定的范围之内. 还要特判最后一个Subtask, ...
- bzoj 4071: [Apio2015]巴邻旁之桥【splay】
用权值线段树会容易一些并快一些,但是想复健一下splay所以打了splay 然后果然不会打了. 解题思路: 首先把家和办公室在同一侧的提出来直接加进答案里: 对于k=1,直接选所有办公室和家的中位数即 ...
- bzoj 4069: [Apio2015]巴厘岛的雕塑【dp】
居然要对不同的数据写不同的dp= = 首先记得开long long,<<的时候要写成1ll<<bt 根据or的性质,总体思路是从大到小枚举答案的每一位,看是否能为0. 首先对于 ...
- 4071: [Apio2015]巴邻旁之桥
Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...
- 巴厘岛的雕塑 BZOJ 4069
巴厘岛的雕塑 题解: 题意是要求分组使每组的和按位取或的值最小 那么考虑贪心,尽量使高位为0 于是枚举位置,从最高位枚举 假设当前枚举到第l位. 令 f[i][j] 表示前 i 个数分成 j 组,满足 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- bzoj千题计划239:bzoj4069: [Apio2015]巴厘岛的雕塑
http://www.lydsy.com/JudgeOnline/problem.php?id=4069 a!=1: 从高位到低位一位一位的算 记录下哪些位必须为0 dp[i][j] 表示前i个数分为 ...
- [BZOJ 4071] 巴邻旁之桥
Link: BZOJ 4071传送门 Solution: 首先算出能提前算的贡献 $K=1$:肯定选中间的点,小学数学 $K=2$:对于每对$(x,y)$一定选离$(x+y)/2$近的桥 也就是说将$ ...
随机推荐
- MyBatis获取SqlSession
package com.ykmimi.dao; import org.apache.ibatis.session.SqlSession; import com.ykmimi.entity.Studen ...
- root权限和sudo得到权限的区别
参考: 知乎 命令前加sudo执行和用真正的root用户执行有什么区别?pansz的回答 root用户和sudo使用root权限的区别 变换用户身份为root的方法su 与 sudo root权限和s ...
- Java Spring-Bean中属性注入
2017-11-06 20:29:13 类属性的注入的三种方法 1.接口方法注入 public interface injection{ public void setName(String name ...
- __all__的作用
https://blog.csdn.net/orangleliu/article/details/49848413
- 使用80percent开发rails程序:gem的了解。(kaminari)
学习目的: 对一些主要的gem进行学习了解基本功能: 作者的一些答复:(链接) 关于安全配置: 对于配置文件, 安全仅有一点: 不要提交任何敏感信息到服务端. 所以 rails-template 是添 ...
- TitanX Server安装Caffe
服务器是Ubuntu Server 16.04,可以ssh和vnc连接. 安装caffe步骤 1. 安装anaconda2:这里不能用3,不知什么原因,cmake错误,无法生成pycaffe 2. 安 ...
- 玲珑杯 round18 A 计算几何瞎暴力
题目链接 : http://www.ifrog.cc/acm/problem/1143 当时没看到坐标的数据范围= =看到讨论才意识到,不同的坐标最多只有1k多个,完全可以暴力做法,不过也要一些技巧. ...
- PHP与Java集成开发详解(一)
很久以前,有人从www上看到看到天空上一个很亮的亮点,它就是Java语言,与此同时,在另一个地方一位梦想家也看到了一个亮点,它就是PHP. 时间一天天过去,这两个亮点也变得越来越亮,很快,它们受到了编 ...
- oracle修改约束列
Oracle 增加修改删除字段 添加字段的语法:alter table tablename add (column datatype [default value][null/not null],-. ...
- Git观察和比较
log git log 时间是从下到上,从远到近 whatchanged git whatchanged 时间是从下到上,从远到近 diff --staged 比较工作区和缓存区之间的差异 g ...