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$近的桥 也就是说将$ ...
随机推荐
- LightOJ 1071 Baker Vai(拆点+最大费用流)题解
题意:给一个n*m的方格,每个格子上都有一个数字表示价值,小A在左上角,他从左上角走到右下角只能向右或向下走,然后再从右下角走上左上角,这次只能向上或向左走,这两条路绝对没有重复,问你怎样走有最大价值 ...
- POJ 1170 Shopping Offers(完全背包+哈希)
http://poj.org/problem?id=1170 题意:有n种花的数量和价格,以及m种套餐买法(套餐会便宜些),问最少要花多少钱. 思路:题目是完全背包,但这道题目不好处理的是套餐的状态, ...
- LA 6892 The Safe Secret(矩阵连乘)
https://vjudge.net/problem/UVALive-6892 题意: 给出n个数字和n个符号(+,-,*和?),?可以为+,-,*中任意一个,现在要计算出这个式子的最小值和最大值,并 ...
- Codeforces Round #404 (Div. 2) A,B,C,D,E 暴力,暴力,二分,范德蒙恒等式,树状数组+分块
题目链接:http://codeforces.com/contest/785 A. Anton and Polyhedrons time limit per test 2 seconds memory ...
- python 执行字符串中的python代码
mycode = 'print("hello world")' code = """ def mutiply(x,y): return x*y pri ...
- __all__的作用
https://blog.csdn.net/orangleliu/article/details/49848413
- [转] oracle 监听
oracle 监听 启动监听:lsnrctl start 查看监听:lsnrctl status 停止监听:lsnrctl stop 1.oracle 数据服务器包括:实例进程和数据库: 实例进程包括 ...
- 记c#中构造函数中this的用法
今天谈及这个话题,是因为在看别人代码,遇到的.本着知其然还要知其所以然的精神,在网上大肆查找了一遍.得到了一些答案.并在此做一个简单的笔记,以便自己和他人以后查找,与我一同成长进步. 在C#中this ...
- python自动化运维之路03
set集合 集合是一个无序的.不可重复的集合.主要作用有: 1.去重,把一个列表变成集合,就等于去重了. 2.关系测试,测试两组数据之前的交集.差集.并集等关系 常用操作 创建.交集.并集.差集.对称 ...
- DOM之一些小实验demo
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...