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$近的桥 也就是说将$ ...
随机推荐
- ubuntu 18.04 64bit如何编译安装内核
1.获取 wget http://mirrors.163.com/kernel/v4.x/linux-4.15.13.tar.gz 2.解压 tar xvf linux-4.15.13.tar.gz ...
- Ajax请求304问题
ajax默认是开启缓存的,所以get请求如果路径一样,会先找缓存,如果缓存存在就用缓存. 解决方案: 1.在修改url为动态变化的,如url后面加一个×tamp=Date.parse ...
- Git WorkBehavior
https://tortoisegit.org/docs/tortoisegit/tgit-dug-showlog.html Repository Demo https://github.com/Ch ...
- AJAX,JSON,GSON
AJAX将数据使用JSON格式发送给后端Servlet或其他语言解析. 对JSON内容使用GSON外扩展包进行分解,并使用(如查询用户名是否已经被注册), 最后使用Map集合设置新的返回状态码,并使用 ...
- Opencv3_Learning
git地址 采用jupyter notebook进行编程,语言为python. 感谢博主--戳 这类东西真的是不是天天打,就是打过就忘.. 有志者事竟成,破釜沉舟,百二秦关终属楚. 苦心人天不负,卧薪 ...
- 浅谈webpack优化
webpack优化方案 1. 优化开发体验 1-1. 加快构建速度 ① 缩小文件搜索范围 由于 Loader 对文件的转换操作很耗时,需要让尽可能少的文件被 Loader 处理,用include和ex ...
- php-----utf8和gbk相互转换
utf8转换为gbk <?php header("Content-type:text/html;charset=UTF-8"); echo $str= '你好,这里是utf8 ...
- LINUX QQ
查询龙井QQ http://www.longene.org/forum/viewtopic.php?f=6&t=4700
- linux 常用操作以及概念
一.常用操作以及概念 查看LINUX发行版的名称及其版本号的命令: lsb_release -a cat /etc/redhat-release(针对redhat,Fedora) 0.rpm包路径:/ ...
- python基础教程笔记 第1单元 && 第2单元
1.http://docs.python.org/dev/3.0/whatsnew/3.0.htmlpython-announce-listpython-help2.交互式编译器3.非整数除法 .1. ...