老师让我们打这套题练练手。感觉这套题还是挺有意思的,比国内某些比赛不知道高到哪里去。最后我拿了284/300,貌似比赛是IOI赛制啊,强行被当成OI赛制做了,不然我T3可能还能多骗点。

T1.sculpture

题目大意:把N个数分成A~B段,使各段和最后或起来最小。(数据组1:N<=100,1<=A<=B<=N;数据组2:N<=2000,A=1<=B<=N)

思路:直接把最后答案从最高位开始按位贪心,能取0就取0,否则取1,判断能否取0可以dp,求是否能分成A~B段使得每一段的和二进制下各位都不超过当前答案(答案一开始二进制全是1),若l~r的和为s,则(s|ans)==ans表示l~r可取成一段,具体DP可以把数据分成两类,1<=A<=B<=N的情况可以用f[i][j]表示1~i能否取成j段,可以O(N^3)DP,A=1时只要贪心使取的段最少,f[i]表示1~i最少取几段,可以O(N^2)DP。最后复杂度再多上外面算答案的log,还是能很科学地通过该题。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define ll long long
inline int read()
{
int x=;char c;
while((c=getchar())<''||c>'');
for(;c>=''&&c<='';c=getchar())x=x*+c-'';
return x;
}
#define MN 2000
#define MN2 100
#define MK 40
int n,l,r,a[MN+];
ll ans=(1LL<<MK+)-;
int f[MN+],f2[MN2+][MN2+];
bool check()
{
int i,j;ll s;
memset(f,,sizeof(f));
for(i=f[]=;i<n;++i)for(s=a[j=i+];j<=n;s+=a[++j])
if((s|ans)==ans&&f[i]+<f[j])f[j]=f[i]+;
return f[n]>r;
}
bool check2()
{
int i,j,k;ll s;
memset(f2,,sizeof(f2));f2[][]=;
for(i=;i<n;++i)for(j=;j<=i;++j)if(f2[i][j])
for(s=a[k=i+];k<=n;s+=a[++k])if((s|ans)==ans)f2[k][j+]=;
for(i=l;i<=r;++i)if(f2[n][i])return ;
return ;
}
int main()
{
freopen("sculpture.in","r",stdin);
freopen("sculpture.out","w",stdout);
n=read();l=read();r=read();
for(int i=;i<=n;++i)a[i]=read();
for(int i=MK;i>=;--i)
{
ans^=1LL<<i;
if(l<?check():check2())ans^=1LL<<i;
}
cout<<ans;
fclose(stdin);fclose(stdout);return ;
}

T2.skyscraper

题目大意:N栋楼,有M个人分布在这些楼中,每个人有自己的行走能力Pi,现在第0号人想通知第1号人,每个被通知过的人可以用1s从自己所在的第k栋楼走到第k-Pi栋或k+Pi栋,也可以0s通知第k楼里所有人,问最少几s第1号人能收到通知,无解输出-1。(N,M<=30000)

思路:考虑直接bfs,用在第i栋楼到达一个能力为j的人表示一个状态,f[i][j]可以拓展到f[i+j][j]或f[i-j][j],第一次到达某一栋楼时可以把整栋里的人对应状态全部加入队列。复杂度看上去是O(N^2),实际上可能被拓展的状态只有O(N*M^0.5),证明:一个在i栋楼能力为j的人拓展出的状态只可能是f[k][j]其中i和k模j同余,或者拓展其他人,对每个人只考虑自己,要最大化状态数,必然使第一个人拓展f[i][1],i%1=0,第二第三个人分别拓展f[i][2],f[j][2],i%2=0,j%2=1……也就是说,要新拓展出n个状态,第i次需要i个人,设最后状态数最多为kn,则k(k+1)/2=m,故k约为M^0.5。N^2的内存肯定开不下,Hash一下就好了。

#include<cstdio>
inline int read()
{
int x=;char c;
while((c=getchar())<''||c>'');
for(;c>=''&&c<='';c=getchar())x=x*+c-'';
return x;
}
#define MN 30000
#define MQ 7500000
#define MOD 9875321
struct MyMap
{
int h[MOD],en,nx[MQ+],t[MQ+],z[MQ+];
int&operator[](int x)
{
for(int i=h[x%MOD];i;i=nx[i])if(t[i]==x)return z[i];
nx[++en]=h[x%MOD];t[en]=x;h[x%MOD]=en;return z[en];
}
}mp;
inline int H(int x,int y){return x*+y;}
struct edge{int nx,t;}e[MN+];
int h[MN+],en,d[MN+],u[MN+],q[MQ+],qp[MQ+],qn;
inline void ins(int x,int y){e[++en]=(edge){h[x],y};h[x]=en;}
void init(int x)
{
for(int i=h[x];i;i=e[i].nx)if(!u[e[i].t])
u[e[i].t]=,q[++qn]=x,qp[qn]=e[i].t,mp[H(x,e[i].t)]=d[x];
for(int i=h[x];i;i=e[i].nx)u[e[i].t]=;
}
int main()
{
freopen("skyscraper.in","r",stdin);
freopen("skyscraper.out","w",stdout);
int n,m,i,j,b,s,t;
n=read();m=read();
for(i=;i<m;++i)
{
b=read();ins(b,read());
if(!i)s=b;if(i==)t=b;
}
for(i=d[s]=,init(s);!d[t]&&i<=qn;++i)
{
int&x=mp[H(q[i],qp[i])];
if((b=q[i]+qp[i])<n)
{
if(!d[b])d[b]=x+,init(b);
int&y=mp[H(b,qp[i])];
if(!y)y=x+,q[++qn]=b,qp[qn]=qp[i];
}
if((b=q[i]-qp[i])>=)
{
if(!d[b])d[b]=x+,init(b);
int&y=mp[H(b,qp[i])];
if(!y)y=x+,q[++qn]=b,qp[qn]=qp[i];
}
}
printf("%d",d[t]-);
fclose(stdin);fclose(stdout);return ;
}

T3.bridge

题目大意:一条河隔开了两岸,两岸各有一排楼,现在给出N条路线,分别是从一栋楼走到另一栋楼(可能过河可能不过),现在要求建K座桥,选定建桥位置使得路线总长最小,求出最小值。(N<=100,000,1<=K<=2)。

思路:不过河的直接加入答案。过河的都当做一条线段,问题变成选K个点使各条线段到最近点距离的和最小。K=1时,选取的点位置即为所有端点的中位数,这是个比较显然的结论,这里不多做说明。K=2时,考虑每条线段最后会选择哪个点作为最近点,可以发现,会选择离它中点最近的点,我们把每条线段按他们的中点位置排序,这样肯定前面一部分选择一座桥,后面的选择另一座桥,而只选一座桥的话就是他们的中位数,我们枚举这个分界点,然后用权值线段树或平衡树维护左右两半的中位数和答案。复杂度O(nlogn)。

这里先贴一个我做这套时写的骗分,K=2时,猜想可能跟K=1时有类似的结论,就是选的第一座桥大约是第n/3大,第二座桥第2n/3大,设定一个搜索半径把n/3和2n/3周围都枚举一下,可以得到一个较优解,这份代码得分是84/100。

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
#define ll long long
inline int read()
{
int x=;char c;
while((c=getchar())<''||c>'');
for(;c>=''&&c<='';c=getchar())x=x*+c-'';
return x;
}
#define MN 100000
inline int get(){for(char c;c=getchar();)if(c>='A'&&c<='B')return c-'A';}
ll ans=1LL<<,s=;
int a[MN+],b[MN+],c[MN*+],cnt;
inline int z(int x){return x<?-x:x;}
void cal(int x,int y)
{
ll p=;int i;
for(i=;i<cnt;++i)
p+=min(z(a[i]-x)+z(b[i]-x),
z(a[i]-y)+z(b[i]-y));
if(p<ans)ans=p;
}
int main()
{
freopen("bridge.in","r",stdin);
freopen("bridge.out","w",stdout);
int k,n,i,j,x;ll p=;
k=read();n=read();
while(n--)
{
x=get();c[cnt]=a[cnt]=read();
if(x==get())s+=z(a[cnt]-read());
else ++s,b[cnt++]=read();
}
for(i=;i<cnt;++i)c[i+cnt]=b[i];n=cnt<<;
sort(c,c+n);
if(k==)
{
for(i=;i<n;++i)p+=c[i]-c[];
if(p<ans)ans=p;
for(i=;i<n;++i)
{
p=p+(ll)((i<<)-n)*(c[i]-c[i-]);
if(p<ans)ans=p;
}
}
else
{
p=cnt<=?:;
for(i=-p;i<=p;++i)if(n/+i>=&&n/+i<n)
for(j=-p;j<=p;++j)if(n*/+j>=&&n*/+j<n)
cal(c[n/+i],c[n*/+j]);
for(i=-p;i<=p;++i)for(j=-p;j<=p;++j)
cal((c[n-]-c[])/+i,(c[n-]-c[])*/+j);
}
cout<<ans+s;
}

正解

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
char B[<<],*S=B,C;int X;
inline int read()
{
while((C=*S++)<''||C>'');
for(X=C-'';(C=*S++)>=''&&C<='';)X=(X<<)+(X<<)+C-'';
return X;
}
inline char get(){while((C=*S++)!='A'&&C!='B');return C-'A';}
#define MN 100000
#define N 262144
ll ans=1LL<<,s=,t[][N*];
int c[MN*+],cn;
struct li{int l,r;}l[MN+];
bool cmp(li a,li b){return a.l+a.r<b.l+b.r;}
inline int z(int x){return x<?-x:x;}
void inc(ll*t,int k,int x){for(k+=N;k;k>>=)t[k]+=x;}
int find(int x)
{
for(int l=,r=cn,mid;;)
{
if(c[mid=l+r>>]==x)return mid;
if(c[mid]<x)l=mid+;
else r=mid-;
}
}
ll query(int p)
{
int k=t[p][]+>>,i,x=;ll r=;
for(i=;i<N;)
if(k<=t[p][i<<])x-=t[p][(i<<)+],r+=t[p+][(i<<)+],i<<=;
else x+=t[p][i<<],k-=t[p][i<<],r-=t[p+][i<<],i=(i<<)+;
return r+(ll)x*c[i-N];
}
int main()
{
fread(B,,<<,stdin);
int k,n,i,cnt=;
k=read();n=read();
while(n--)
{
i=get();l[cnt].l=read();
if(i==get())s+=z(l[cnt].l-read());
else ++s,c[++cn]=l[cnt].l,c[++cn]=l[cnt++].r=read();
}
sort(c+,c+cn+);sort(l,l+cnt,cmp);
for(c[n=]=-,i=;i<=cn;++i)if(c[i]!=c[i-])c[++n]=c[i];cn=n;
for(i=;i<cnt;++i)
{
l[i].l=find(l[i].l);inc(t[],l[i].l,);inc(t[],l[i].l,c[l[i].l]);
l[i].r=find(l[i].r);inc(t[],l[i].r,);inc(t[],l[i].r,c[l[i].r]);
}
if(k<)return printf("%lld",query()+s),;
for(i=;i<cnt;++i)
{
inc(t[],l[i].l,);inc(t[],l[i].r,);
inc(t[],l[i].l,c[l[i].l]);inc(t[],l[i].r,c[l[i].r]);
inc(t[],l[i].l,-);inc(t[],l[i].r,-);
inc(t[],l[i].l,-c[l[i].l]);inc(t[],l[i].r,-c[l[i].r]);
ans=min(ans,query()+query());
}
printf("%lld",ans+s);
}

APIO 2015的更多相关文章

  1. 【CTSC 2015】&【APIO 2015】酱油记

    蒟蒻有幸参加了神犇云集的CTSC & APIO 2015,感觉真是被虐成傻逼了……这几天一直没更新博客,今天就来补一下吧~~(不过不是题解……) Day 0 从太原到北京现在坐高铁只需3小时= ...

  2. CTSC&&APIO 2015 酱油记

    在北京待了一周多,还是写点记录吧. 人民大学校园还是挺不错的,不过伙食差评. CTSC的题目太神,根本不会搞,一试20二试10分..本来都寄希望于提交答案题的..结果就悲剧了. 然后是听大爷们的论文答 ...

  3. 解题:APIO 2015 雅加达的摩天大楼

    题面 分块思想+最短路 发现对于步长小的doge会连出很多边,很容易导致大量的重边,于是对doge们根据步长分块讨论:根据步长建出分层图,然后把步长不超过某个值的doge们连到对应层上的点上,其余的d ...

  4. 【UOJ #112】【APIO 2015】Palembang Bridges

    http://uoj.ac/problem/112 先扣掉在同一侧的情况. 当\(k=1\)时,桥建在所有位置的中位数. 当\(k=2\)时,对于每个居民\((S_i,T_i)\),这个居民只会走离\ ...

  5. 【BZOJ 4070】【APIO 2015】雅加达的摩天楼

    http://www.lydsy.com/JudgeOnline/problem.php?id=4070 分块建图. 对每个\(P_i\)分类讨论,\(P_i>\sqrt N\)则直接连边,边数 ...

  6. 【UOJ #110】【APIO 2015】Bali Sculptures

    http://uoj.ac/problem/110 这道题subtask4和subtask5是不同的算法. 主要思想都是从高位到低位贪心确定答案. 对于subtask4,n比较小,设\(f(i,j)\ ...

  7. [APIO 2015] 雅加达的摩天楼

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4070 [算法] 考虑将每个"Doge"向其所能到达的楼连边 直接 ...

  8. 2015 CTSC & APIO滚粗记

    o诶人太弱..... 记一发滚粗记以便治疗我的健忘症= = //文章会不定时修改,添加一些内容什么的...因此最好看一下刷新一下(因为有可能你正在看= =我正在写... 5.2 早上9点坐上长达11小 ...

  9. 2015 西雅图微软总部MVP峰会记录

    2015 西雅图微软总部MVP峰会记录 今年决定参加微软MVP全球峰会,在出发之前本人就已经写这篇博客,希望将本次会议原汁原味奉献给大家 因为这次是本人第一次写会议记录,写得不好的地方希望各位园友见谅 ...

随机推荐

  1. 敏捷冲刺每日报告——Day2

    1.情况简述 Alpha阶段第一次Scrum Meeting 敏捷开发起止时间 2017.10.26 00:00 -- 2017.10.27 00:00 讨论时间地点 2017.10.26晚9:30, ...

  2. 201621123050 《Java程序设计》第1周学习总结

    1.本周学习总结 java历史概述 java特点:1.简单 2.面向对象 3.健壮 4.跨平台 5.类库众多 JDK.JRE.JVM JDK:JAVA 开发工具包 ,包含JRE JRE: JAVA运行 ...

  3. 20145237 《Java程序设计》第10周学习总结

    20145237 <Java程序设计>第10周学习总结 教材学习内容总结 Java的网络编程 •网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来. •java.n ...

  4. python3.* socket例子

    On Server: # -*- coding: utf-8 -*-#this is the server import socketif "__main__" == __name ...

  5. 【iOS】swift 74个Swift标准库函数

    本文译自 Swift Standard Library: Documented and undocumented built-in functions in the Swift standard li ...

  6. bzoj千题计划243:bzoj2325: [ZJOI2011]道馆之战

    http://www.lydsy.com/JudgeOnline/problem.php?id=2325 设线段树节点区间为[l,r] 每个节点维护sum[0/1][0/1]  从l的A/B区域到r的 ...

  7. zookeeper入门系列:paxos协议

    上一章讨论了一种强一致性的情况,即需要分布式事务来解决,本章我们来讨论一种最终一致的算法,paxos算法. paxos算法是由大牛lamport发明的,关于paxos算法有很多趣事.比如lamport ...

  8. prop attr 到底哪里不一样?

    好吧 首先承认错误  说好的每天进行一次只是总结  但是我没坚持住 准确的来说 我并没有每天会学到了东西 但是 我一直在持续努力着  以后应该不会每天都写  但是自己觉得有用的  或者想加强记忆的 可 ...

  9. service层报错找不到方法Invalid bound statement (not found)

    报错信息如下 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.imooc.se ...

  10. php的set_time_limit()函数

    set_time_limit(0); 括号里边的数字是执行时间,如果为零说明永久执行直到程序结束,如果为大于零的数字,则不管程序是否执行完成,到了设定的秒数,程序结束. 一个简单的例子,在网页里显示1 ...