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[2007];
i64 s[2007],ans=0;
std::bitset<207>d[207];
int main(){
    scanf("%d%d%d",&n,&A,&B);
    for(int i=1;i<=n;++i)scanf("%lld",s+i),s[i]+=s[i-1];
    if(A==1){
        for(int x=50;x>=0;--x){
            i64 v=ans|((1ll<<x)-1);
            for(int i=1;i<=n;++i){
                f[i]=0x3f3f3f3f;
                for(int j=0;j<i;++j)if(((s[i]-s[j])|v)==v&&f[j]+1<f[i])f[i]=f[j]+1;
            }
            if(f[n]>B)ans|=1ll<<x;
        }
    }else{
        d[0][0]=1;
        for(int x=50;x>=0;--x){
            i64 v=ans|((1ll<<x)-1);
            for(int i=1;i<=n;++i){
                d[i].reset();
                for(int j=0;j<i;++j)if(((s[i]-s[j])|v)==v)
                d[i]|=d[j]<<1;
            }
            bool dd=0;
            for(int i=A;i<=B;++i)dd|=d[n][i];
            if(!dd)ans|=1ll<<x;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

T2

对每个不同的(p[i],b[i]%p[i]),新建一些点表示这个i可以走到的位置,每个位置和每个i也建出对应的点

最后可以转为01边权最短路

可以证明时空复杂度均为$O(n^\frac 3 2)$

#include<bits/stdc++.h>
const int inf=0x3f3f3f3f,C=300;
int n,m,b[30007],p[30007],B;
struct edge{
    int to;
    edge*nx;
}*ep=0,*mep=0;
edge*e0[30007*C];
int l[30007*C];
bool is[30007*C];
void ae(int a,int b){
    if(ep==mep)ep=new edge[10000],mep=ep+10000;
    *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+1)q.push_back((node){u,::l[u]=l+1});
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;++i)scanf("%d%d",b+i,p+i);
    idp=n+m;
    for(int i=0;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<<15|y];
        if(!z){
            z=idp;
            int a;
            for(a=y;a+x<n;a+=x){
                is[idp]=1;
                ae(idp++,a);
            }
            ae(idp++,a);
        }
        ae(n+i,z+(b[i]-y)/x);
    }
    std::fill(l,l+idp+1,inf);
    q.push_back((node){n,l[n]=0});
    while(!q.empty()){
        node w=q.front();q.pop_front();
        if(w.l!=l[w.w])continue;
        if(w.w==n+1)return printf("%d\n",w.l),0;
        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-1])w.upd1(w.w-1);
        if(is[w.w])w.upd1(w.w+1);
    }
    return puts("-1"),0;
}

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[2],s2[2];
int p1,p2,xs[200007],xp=0;
i64 ans=0;
int abs(int x){return x>0?x:-x;}
struct pos{
    int a,b;
    bool operator<(pos w)const{return a+b<w.a+w.b;}
}ps[100007];
int pp=0;
i64 ss1=0,ss2=0,f[100007];
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=0;
}
void ins(int x){
    if(q1.size()&&x<=q1.top()){
        q1.push(x),ss1+=x;
        if(q1.size()>q2.size()+1){
            int x=q1.top();q1.pop();
            ss1-=x;ss2+=x;
            q2.push(x);
        }
    }else{
        q2.push(x),ss2+=x;
        if(q2.size()>q1.size()+1){
            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==1){
        for(int t=0;t<n;++t){
            scanf("%s%d%s%d",s1,&p1,s2,&p2);
            if(s1[0]==s2[0])ans+=abs(p2-p1);
            else ++ans,xs[xp++]=p1,xs[xp++]=p2;
        }
        if(xp){
            std::nth_element(xs,xs+xp/2,xs+xp);
            int x=xs[xp/2];
            for(int a=0;a<xp;++a)ans+=abs(xs[a]-x);
        }
    }else{
        for(int t=0;t<n;++t){
            scanf("%s%d%s%d",s1,&p1,s2,&p2);
            if(s1[0]==s2[0])ans+=abs(p2-p1);
            else ++ans,ps[pp++]=(pos){p1,p2};
        }
        std::sort(ps,ps+pp);
        if(pp){
            init();
            for(int a=0;a<pp;++a){
                ins(ps[a].a);ins(ps[a].b);
                f[a]=cal();
            }
            i64 mx=f[pp-1];
            init();
            for(int a=pp-1;a;--a){
                ins(ps[a].a);ins(ps[a].b);
                mins(mx,cal()+f[a-1]);
            }
            ans+=mx;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

时间: 2024-10-24 05:51:39

bzoj 4069~4071 APIO2015的相关文章

【BZOJ 4069】[apio2015]巴厘岛的雕塑

4069:[apio2015]巴厘岛的雕塑 Time limit: 1000 ms Memory limit: 65536 KB Description The province of Bali has many sculptures located on its roads. Let's focus on one of its main roads. There are N sculptures on that main road, conveniently numbered 1 throug

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

[Apio2015]巴厘岛的雕塑 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 494  Solved: 238[Submit][Status][Discuss] Description 印尼巴厘岛的公路上有许多的雕塑,我们来关注它的一条主干道. 在这条主干道上一共有 N 座雕塑,为方便起见,我们把这些雕塑从 1 到 N 连续地进行标号,其中第 i 座雕塑的年龄是 Yi 年.为了使这条路的环境更加优美,政府想把这些雕塑分成若干组,并通过在组与组之间

【BZOJ 4070】 [Apio2015]雅加达的摩天楼

4070: [Apio2015]雅加达的摩天楼 Time limit: 1000 ms Memory limit: 262144 KB Description The city of Jakarta has N skyscrapers located on a line, conveniently numbered 0 through N-1 from left to right. There are no other skyscrapers in Jakarta. Jakarta is inh

4071: [Apio2015]巴邻旁之桥

Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1000000000.相邻的每对建筑相隔 1 个单位距离,河的宽度也是 1 个单位长度.区域 A 中的 i 号建筑物恰好与区域 B 中的 i 号建筑物隔河相对. 城市中有 N 个居民.第 i 个居民的房子在区域 Pi 的 Si 号建筑上,同时他的办公室坐落在 Qi 区域的 Ti 号建筑上.一个居民的房子和办公

【BZOJ 4071】[apio2015]巴邻旁之桥

4071:[apio2015]巴邻旁之桥 Time limit: 2000 ms Memory limit: 262144 KB Description The city of Palembang is separated by Musi River into two zones. Let's call them zone A and zone B. Each zone consists of exactly 1,000,000,001 buildings along the respectiv

【水】Nocomachns定理

Nocomachns定理 题目描述 数学上已证明:任何一个自然数n的3次方可以表示为n个连续奇数之和,例如3的3次方为27=7+9+11.试编程求出,当键盘输入一个自然数时,求出它3次方的值及其连续奇数之和. 输入 一个整数N(N<=100) 输出 N的三次方的分解,格式如样列. 样例输入 3 样例输出 3^3=7+9+11 分析 一定要认真看题目...n个连续奇数,如果早看到就没那么麻烦了.... 这题标准解法应该是这样滴: n^3=n*n^2,所以这n个奇数是以n^2为对称轴的n个奇数...

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

http://www.lydsy.com/JudgeOnline/problem.php?id=4069 a!=1: 从高位到低位一位一位的算 记录下哪些位必须为0 dp[i][j] 表示前i个数分为j组,这一位为0,且满足之前必须为0的位也是0 是否可行 枚举k,表示k+1~i分为一组 若k+1~i的和满足 必须为0的位是0,且dp[k][j-1] 为true 则dp[i][j]为true a=1: 从高位到低位一位一位的算 记录下哪些位必须为0 dp[i] 表示前i个数,这一位为0,且满足之

BZOJ 4070: [Apio2015]雅加达的摩天楼

Descrption 有\(m\)只doge,每只doge只能到\(b_i+kp_i,k\in Z\),求0号doge将信息传给1号doge的最少跳跃步数.\(n\leqslant 3\times 10^4\) Solution 分块. 将\(p\)分成大于\(\sqrt n\)和小于等于\(\sqrt n\)的两部分,然后小于的部分可以暴力建好图再连边,大于的部分直接连所有能到达的位置即可. 复杂度\(O(n\sqrt n)\). PS:UOJ上过不了Extra Text... 其实时间复杂度

4069: [Apio2015]巴厘岛的雕塑

Description 印尼巴厘岛的公路上有许多的雕塑,我们来关注它的一条主干道. 在这条主干道上一共有 N 座雕塑,为方便起见,我们把这些雕塑从 1 到 N 连续地进行标号,其中第 i 座雕塑的年龄是 Yi 年.为了使这条路的环境更加优美,政府想把这些雕塑分成若干组,并通过在组与组之间种上一些树,来吸引更多的游客来巴厘岛. 下面是将雕塑分组的规则: 这些雕塑必须被分为恰好 X 组,其中 A< = X< = B,每组必须含有至少一个雕塑,每个雕塑也必须属于且只属于一个组.同一组中的所有雕塑必须