uoj123 【NOI2013】小Q的修炼
搞了一下午+半晚上。其实不是很难。
提答题重要的是要发现数据的特殊性质,然后根据不同数据写出不同的算法获得其对应的分数。
首先前两个测试点我们发现可以直接暴搜通过,事实上对于每个数据都暴搜加上一定的次数限制,都可以获得两分的好成绩。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m,a[],ans=-0x7fffffff;
int fin[],st[];
struct num{
int x1,x2;
num(){x1=x2=;}
num(int x,char o){
if(o=='v')x1=x,x2=;
else x1=,x2=x;
}
};
struct data{
char o,f;
num x,y;
int s1,s2;
}d[];
char getc(){
char ch=getchar();
while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
ch=getchar();
return ch;
}
void dfs(int x,int step){
if(x>n||x<){
if(a[]>ans){
for(int i=;i<step;i++)
fin[i]=st[i];
ans=a[];
}
return ;
}
if(d[x].o=='v'){
int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(d[x].f=='+')a[d[x].x.x1]+=now;
else a[d[x].x.x1]-=now;
dfs(x+,step);
if(d[x].f=='+')a[d[x].x.x1]-=now;
else a[d[x].x.x1]+=now;
}
if(d[x].o=='i'){
int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(x1<x2)dfs(d[x].s1,step);
else dfs(d[x].s2,step);
}
if(d[x].o=='s'){
st[step]=,dfs(d[x].s1,step+);
st[step]=,dfs(d[x].s2,step+);
}
}
int read(){
int a=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){a=a*+ch-'';ch=getchar();}
return a*f;
}
int main(){
freopen("train1.in","r",stdin);
freopen("train1.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
d[i].o=getc();
if(d[i].o=='v'){
d[i].x=num(read(),'v');
d[i].f=getc();
d[i].y=num(read(),getc());
}
else if(d[i].o=='s'){
d[i].s1=read();
d[i].s2=read();
}
else if(d[i].o=='i'){
d[i].x=num(read(),getc());
d[i].y=num(read(),getc());
d[i].s1=read();
d[i].s2=read();
}
}
dfs(,);
for(int i=;fin[i];i++)
printf("%d\n",fin[i]);
return ;
}
对于第三个测试点,我们可以发现这其实是分成了好多独立的块,长度是170,我们发现,在块内有不多的决策点,然后块的末尾会将所有变量都加给1,然后清零,所以我们可以每个块内暴搜,然后合并起来。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m,a[],ans=-0x7fffffff;
int fin[],st[];
struct num{
int x1,x2;
num(){x1=x2=;}
num(int x,char o){
if(o=='v')x1=x,x2=;
else x1=,x2=x;
}
};
struct data{
char o,f;
num x,y;
int s1,s2;
}d[];
char getc(){
char ch=getchar();
while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
ch=getchar();
return ch;
}
void dfs(int x,int step,int pos){
if(x>(pos*)||x<=(pos-)*){
if(a[]>ans){
for(int i=;i<step;i++)
fin[i]=st[i];
ans=a[];
}
return ;
}
if(d[x].o=='v'){
int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(d[x].f=='+')a[d[x].x.x1]+=now;
else a[d[x].x.x1]-=now;
dfs(x+,step,pos);
if(d[x].f=='+')a[d[x].x.x1]-=now;
else a[d[x].x.x1]+=now;
}
if(d[x].o=='i'){
int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(x1<x2)dfs(d[x].s1,step,pos);
else dfs(d[x].s2,step,pos);
}
if(d[x].o=='s'){
st[step]=,dfs(d[x].s1,step+,pos);
st[step]=,dfs(d[x].s2,step+,pos);
}
}
int read(){
int a=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){a=a*+ch-'';ch=getchar();}
return a*f;
}
int main(){
freopen("train3.in","r",stdin);
freopen("train3.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
d[i].o=getc();
if(d[i].o=='v'){
d[i].x=num(read(),'v');
d[i].f=getc();
d[i].y=num(read(),getc());
}
else if(d[i].o=='s'){
d[i].s1=read();
d[i].s2=read();
}
else if(d[i].o=='i'){
d[i].x=num(read(),getc());
d[i].y=num(read(),getc());
d[i].s1=read();
d[i].s2=read();
}
}
for(int i=;i<=;i++){
ans=-0x7fffffff;
memset(fin,,sizeof fin);
memset(a,,sizeof a);
dfs((i-)*+,,i);
for(int i=;fin[i];i++)
printf("%d\n",fin[i]);
}
return ;
}
对于456个测试点,我们发现只有两个变量,相当于是用钱买成就,于是我们可以做一个简单的dp,注意56两个点不一定跳到后面相邻的那个,所以又多了不少细节。我的f[i][j]表示在i处买完剩了j元钱的答案,g表示不在这里买。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
int n,m,a[],ans=-0x7fffffff;
int fin[],st[];
struct num{
int x1,x2;
num(){x1=x2=;}
num(int x,char o){
if(o=='v')x1=x,x2=;
else x1=,x2=x;
}
};
struct data{
char o,f;
num x,y;
int s1,s2,id;
}d[];
char getc(){
char ch=getchar();
while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
ch=getchar();
return ch;
}
int read(){
int a=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){a=a*+ch-'';ch=getchar();}
return a*f;
}
int f[][],g[][],pp[];
int c[],w[],tot,pf[][],pg[][];
vector<int> pr[];
void dfs(int x,int y,int o){
if(!x)return ;
if(o==||y>=c[x])fin[x]=o;
else fin[x]=;
if(o==){
if(pf[x][y])dfs(pf[x][y],y+c[x],);
else dfs(x-,y+c[x],);
}
else{
if(pg[x][y])dfs(pg[x][y],y,);
else dfs(x-,y,);
}
}
int main(){
freopen("train6.in","r",stdin);
freopen("train6.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
d[i].o=getc();
if(d[i].o=='v'){
d[i].x=num(read(),'v');
d[i].f=getc();
d[i].y=num(read(),getc());
if(i==){d[i].id=;continue;}
if(d[i].x.x1==)c[++tot]=d[i].y.x2;
else w[tot]=d[i].y.x2;
d[i].id=tot;
}
else if(d[i].o=='s'){
pp[tot+]=i;
d[i].id=tot+;
d[i].s1=read();
d[i].s2=read();
}
else if(d[i].o=='i'){
d[i].id=tot+;
d[i].x=num(read(),getc());
d[i].y=num(read(),getc());
d[i].s1=read();
d[i].s2=read();
}
}
d[].id=tot+;
for(int i=;i<=tot;i++)
pr[d[d[pp[i]].s2].id].push_back(i);
memset(f,-0x3f,sizeof f);
f[][]=;
int p1,p2;
for(int i=;i<=tot;i++){
for(int j=c[i];j<=;j++){
f[i][j-c[i]]=f[i-][j]+w[i];
pf[i][j-c[i]]=;
for(int k=;k<pr[i].size();k++)if(g[pr[i][k]][j]+w[i]>f[i][j-c[i]]){
f[i][j-c[i]]=g[pr[i][k]][j]+w[i];
pf[i][j-c[i]]=pr[i][k];
}
if(f[i][j-c[i]]>ans){
ans=f[i][j-c[i]];
p1=i;p2=j-c[i];
}
}
for(int j=;j<=;j++){
g[i][j]=f[i-][j];
pg[i][j]=;
for(int k=;k<pr[i].size();k++)if(g[pr[i][k]][j]>g[i][j]){
g[i][j]=g[pr[i][k]][j];
pg[i][j]=pr[i][k];
}
}
}
dfs(p1,p2,);
for(int i=;i<=tot;i++)if(fin[i])printf("%d\n",fin[i]);
return ;
}
最后四个点我们发现明显就是暴搜和dp拼起来,我们对于每个块内搜出他的贡献,然后和上面一样dp就好了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
int n,m,a[],ans=-0x7fffffff;
int fin[][],st[];
int f[][],g[][],pp[];
int c[],w[],tot,pf[][],pg[][];
vector<int> pr[];
struct num{
int x1,x2;
num(){x1=x2=;}
num(int x,char o){
if(o=='v')x1=x,x2=;
else x1=,x2=x;
}
};
struct data{
char o,f;
num x,y;
int s1,s2,id;
}d[];
char getc(){
char ch=getchar();
while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
ch=getchar();
return ch;
}
int be,en;
void dfs(int x,int step,int pos){
if(x>en||x<be){
if(a[]>w[pos]){
for(int i=;i<step;i++)
fin[pos][i]=st[i];
w[pos]=a[];
}
return ;
}
if(d[x].o=='v'){
int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(d[x].f=='+')a[d[x].x.x1]+=now;
else a[d[x].x.x1]-=now;
dfs(x+,step,pos);
if(d[x].f=='+')a[d[x].x.x1]-=now;
else a[d[x].x.x1]+=now;
}
if(d[x].o=='i'){
int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(x1<x2)dfs(d[x].s1,step,pos);
else dfs(d[x].s2,step,pos);
}
if(d[x].o=='s'){
st[step]=,dfs(d[x].s1,step+,pos);
st[step]=,dfs(d[x].s2,step+,pos);
}
}
int read(){
int a=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){a=a*+ch-'';ch=getchar();}
return a*f;
}
void dfs1(int x,int y,int o){
if(!x)return ;
if(o==||y>=c[x])fin[x][]=o;
else fin[x][]=;
if(o==){
if(pf[x][y])dfs1(pf[x][y],y+c[x],);
else dfs1(x-,y+c[x],);
}
else{
if(pg[x][y])dfs1(pg[x][y],y,);
else dfs1(x-,y,);
}
}
int main(){
freopen("train10.in","r",stdin);
freopen("train10.out","w",stdout);
scanf("%d%d",&n,&m);
memset(w,-0x3f,sizeof w);
for(int i=;i<=n;i++){
d[i].o=getc();
if(d[i].o=='v'){
d[i].x=num(read(),'v');
d[i].f=getc();
d[i].y=num(read(),getc());
if(i==){d[i].id=;continue;}
if(d[i].x.x1==){
c[tot]=d[i].y.x2;
be=i+;
}
d[i].id=tot;
}
else if(d[i].o=='s'){
d[i].s1=read();
d[i].s2=read();
d[i].id=tot;
if(!pp[tot])pp[tot]=i;
}
else if(d[i].o=='i'){
d[i].x=num(read(),getc());
d[i].y=num(read(),getc());
d[i].s1=read();
d[i].s2=read();
if(d[i].x.x1==){
if(tot){en=i-;dfs(be,,tot);}
tot++;
for(int j=i-;d[j].o=='i'&&d[j].s2==;j--)
d[j].id=tot;
}
d[i].id=tot;
}
}
en=n;
dfs(be,,tot);
for(int i=;i<=tot;i++)
pr[d[d[pp[i]].s2].id].push_back(i);
memset(f,-0x3f,sizeof f);
f[][]=;
int p1,p2;
for(int i=;i<=tot;i++){
for(int j=c[i];j<=;j++){
f[i][j-c[i]]=f[i-][j]+w[i];
pf[i][j-c[i]]=;
for(int k=;k<pr[i].size();k++)if(g[pr[i][k]][j]+w[i]>f[i][j-c[i]]){
f[i][j-c[i]]=g[pr[i][k]][j]+w[i];
pf[i][j-c[i]]=pr[i][k];
}
if(f[i][j-c[i]]>ans){
ans=f[i][j-c[i]];
p1=i;p2=j-c[i];
}
}
for(int j=;j<=;j++){
g[i][j]=f[i-][j];
pg[i][j]=;
for(int k=;k<pr[i].size();k++)if(g[pr[i][k]][j]>g[i][j]){
g[i][j]=g[pr[i][k]][j];
pg[i][j]=pr[i][k];
}
}
}
dfs1(p1,p2,);
for(int i=;i<=tot;i++)if(fin[i][]){
printf("%d\n",fin[i][]);
if(fin[i][]==){
for(int j=;fin[i][j];j++)
printf("%d\n",fin[i][j]);
}
}
return ;
}
提答,提答。
uoj123 【NOI2013】小Q的修炼的更多相关文章
- 「NOI2013」小 Q 的修炼 解题报告
「NOI2013」小 Q 的修炼 第一次完整的做出一个提答,花了半个晚上+一个上午+半个下午 总体来说太慢了 对于此题,我认为的难点是观察数据并猜测性质和读入操作 我隔一会就思考这个sb字符串读起来怎 ...
- 【NOI2013】小Q的修炼
题目链接:http://uoj.ac/problem/123 又开提答坑啦,要不是一定要讲题谁他妈要这样伤害自己 CASE 1,2 首先可以打一个通用暴力,用于模拟操作过程,对于每一个操作随机一个选择 ...
- HD4505小Q系列故事——电梯里的爱情
Problem Description 细心的同事发现,小Q最近喜欢乘电梯上上下下,究其原因,也许只有小Q自己知道:在电梯里经常可以遇到他心中的女神HR. 电梯其实是个很暧昧的地方,只有在电梯里,小Q ...
- hdu4505小Q系列故事——电梯里的爱情
小Q系列故事——电梯里的爱情 Time Limit: 300/100 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tota ...
- 小Q系列故事——电梯里的爱情
小Q系列故事——电梯里的爱情 Time Limit : 300/100ms (Java/Other) Memory Limit : 65535/32768K (Java/Other) Total ...
- 平面直接坐标系线段相交问题(小Q(钟神)的问题)
[问题描述] 小 Q 对计算几何有着浓厚的兴趣.他经常对着平面直角坐标系发呆,思考一些有趣的问题.今天,他想到了一个十分有意思的题目:首先,小 Q 会在?轴正半轴和?轴正半轴分别挑选?个点.随后,他将 ...
- hdu---(4515)小Q系列故事——世界上最遥远的距离(模拟题)
小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)T ...
- HDU-4515 小Q系列故事——世界上最遥远的距离
小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) ...
- 2013腾讯编程马拉松初赛第二场(3月22日) 小Q系列故事——为什么时光不能倒流 ---好水!!
我以为我会是最坚强的那一个 我还是高估了自己 我以为你会是最无情的那一个 还是我贬低了自己 就算不能够在一起 我还是为你担心 就算你可能听不清 也代表我的心意 那北极星的眼泪 闪过你曾经的眼角迷离 那 ...
随机推荐
- 终结python协程----从yield到actor模型的实现
把应用程序的代码分为多个代码块,正常情况代码自上而下顺序执行.如果代码块A运行过程中,能够切换执行代码块B,又能够从代码块B再切换回去继续执行代码块A,这就实现了协程 我们知道线程的调度(线程上下文切 ...
- Web服务cxf框架发布2
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本人声明.否则将追究法律责任. 作者:永恒の_☆ 地址:http://blog.csdn.net/chenghui0317/ ...
- Java容器:List
集合类的层次关系 List接口简介 List的常用方法 List实例 Vector ArrayList Vector和ArrayList的扩容 LinkedList 参考文章 今天开始更新Java集合 ...
- python爬虫人门(10)Scrapy框架之Downloader Middlewares
设置下载中间件(Downloader Middlewares) 下载中间件是处于引擎(crawler.engine)和下载器(crawler.engine.download())之间的一层组件,可以有 ...
- vue.js常见的报错信息及其解决方法的记录
1.Vue packages version mismatch 翻译:vue包版本匹配错误 报错样例: 报错原因:通常出现于一些依赖库的更新或者安装新的依赖库之后(可以认为npm update已经成为 ...
- QT5:C++实现基于multimedia的音乐播放器(二)
今天接着上一篇来实现播放器的槽函数. 先来实现播放模式,槽函数如下: //播放模式 void Music::musicPlayPattern() { //z=++z%3; ) { //顺序播放 pla ...
- Tiny4412之串口(Uart)驱动编写
一:tiny4412串口驱动编写 1.串口通信简介 串口通信指串口按位(bit)发送和接收字节,串口通信的概念非常简单,串口按位(bit)发送和接收字节.尽管比按字节(byte)的并行通信慢,但是串口 ...
- Spring MVC温故而知新-从零开始
Spring MVC简介 Spring MVC是一款基于MVC架构模式的轻量级Web框架,目的是将Web开发模块化,对整体架构进行解耦. Spring MVC有一下优点: 作为Spring框架的一部分 ...
- 《嵌入式Linux内存使用与性能优化》笔记
这本书有两个关切点:系统内存(用户层)和性能优化. 这本书和Brendan Gregg的<Systems Performance>相比,无论是技术层次还是更高的理论都有较大差距.但是这不影 ...
- 20.QT-Qpixmap实现图片鼠标缩放,鼠标拖动示例(详解)
通过 QPainter 绘画实现,以本地图片985*740为例 如下图所示: 效果如下所示: 实现原理 主要通过以下函数实现: , ); //平铺显示pixmap //x y w h :表示绘画区域 ...