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的更多相关文章

  1. bzoj 4069 [Apio2015]巴厘岛的雕塑 dp

    [Apio2015]巴厘岛的雕塑 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 494  Solved: 238[Submit][Status][Dis ...

  2. BZOJ 4069 [Apio2015]巴厘岛的雕塑 ——贪心

    自己首先想了一种方法$f(i)$表示前$i$个最小值为多少. 然而发现位运算并不满足局部最优性. 然后我们可以从高到低贪心的判断,使得每一组的和在一个特定的范围之内. 还要特判最后一个Subtask, ...

  3. bzoj 4071: [Apio2015]巴邻旁之桥【splay】

    用权值线段树会容易一些并快一些,但是想复健一下splay所以打了splay 然后果然不会打了. 解题思路: 首先把家和办公室在同一侧的提出来直接加进答案里: 对于k=1,直接选所有办公室和家的中位数即 ...

  4. bzoj 4069: [Apio2015]巴厘岛的雕塑【dp】

    居然要对不同的数据写不同的dp= = 首先记得开long long,<<的时候要写成1ll<<bt 根据or的性质,总体思路是从大到小枚举答案的每一位,看是否能为0. 首先对于 ...

  5. 4071: [Apio2015]巴邻旁之桥

    Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...

  6. 巴厘岛的雕塑 BZOJ 4069

    巴厘岛的雕塑 题解: 题意是要求分组使每组的和按位取或的值最小 那么考虑贪心,尽量使高位为0 于是枚举位置,从最高位枚举 假设当前枚举到第l位. 令 f[i][j] 表示前 i 个数分成 j 组,满足 ...

  7. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  8. bzoj千题计划239:bzoj4069: [Apio2015]巴厘岛的雕塑

    http://www.lydsy.com/JudgeOnline/problem.php?id=4069 a!=1: 从高位到低位一位一位的算 记录下哪些位必须为0 dp[i][j] 表示前i个数分为 ...

  9. [BZOJ 4071] 巴邻旁之桥

    Link: BZOJ 4071传送门 Solution: 首先算出能提前算的贡献 $K=1$:肯定选中间的点,小学数学 $K=2$:对于每对$(x,y)$一定选离$(x+y)/2$近的桥 也就是说将$ ...

随机推荐

  1. ASP.NET WEB API 2: HTTP MESSAGE LIFECYLE

    https://www.asp.net/media/4071077/aspnet-web-api-poster.pdf 1.You can host Web API inside IIS or ins ...

  2. github上fork别人的代码之后,如何保持和原作者同步的更新

    1.从自己fork之后的版本库clone $  git clone -o chucklu https://github.com/chucklu/Hearthstone-Deck-Tracker.git ...

  3. AIM Tech Round 5 (rated, Div. 1 + Div. 2)

    A. Find Square 找到对角线的两个点的坐标,这道题就迎刃而解了. inline void work(int n) { int m; cin >> m; memset(str, ...

  4. Numpy 练习题

    1. 使用循环和向量化两种不同的方法来计算 100 以内的质数之和. 先定义个判断质数的函数.ps:纯手工打造,原生态,哈哈. def checkprime(x): if x<=1: retur ...

  5. 获取主机的对外ip

    # curl -w "\n" ifconfig.me # curl -w "\n" ipinfo.io/json # curl -w "\n" ...

  6. spark 累加历史 + 统计全部 + 行转列

    spark 累加历史主要用到了窗口函数,而进行全部统计,则需要用到rollup函数 1  应用场景: 1.我们需要统计用户的总使用时长(累加历史) 2.前台展现页面需要对多个维度进行查询,如:产品.地 ...

  7. m_Orchestrate learning system---网站的语言选择功能(中文英文)

    m_Orchestrate learning system---网站的语言选择功能(中文英文) 一.总结 一句话总结:有两种方法,一是session+js端代码,而是session+php端代码. 推 ...

  8. React中使用UEditor

    一般UEditor用于表单的新建和编辑 <FormItem {...formItemLayout} label='商品详情'> {getFieldDecorator('detail', { ...

  9. chrome插件访问原始页面的变量

    开发chrome插件时遇到需要获取原始网页中的一个js变量的值问题.由于content.js和原始网页的作用域环境不同,无法直接获取变量的值,提示undefined.谷歌找到大神提供的办法.综合起来记 ...

  10. const关键字对C++成员函数的修饰

    const对C++成员函数的修饰分为三种:1. 修饰参数:2. 修饰返回值:3. 修饰this指针.简述一下知识点如下,以后找功夫再完善. 1. 对函数参数的修饰. 1)const只能用来修饰输入参数 ...