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系列故事——为什么时光不能倒流 ---好水!!
我以为我会是最坚强的那一个 我还是高估了自己 我以为你会是最无情的那一个 还是我贬低了自己 就算不能够在一起 我还是为你担心 就算你可能听不清 也代表我的心意 那北极星的眼泪 闪过你曾经的眼角迷离 那 ...
随机推荐
- post请求参数Json字符串包含数组的校验和处理 -工作随记-备查工具
package com.xxxx.live.webapp.selvert; import java.io.BufferedReader; import java.io.IOException; imp ...
- c语言,文件操作总结
C语言文件操作 一.标准文件的读写 1.文件的打开 fopen() 文件的打开操作表示将给用户指定的文件在内存分配一个FILE结构区,并将该结构的指针返回给用户程序,以后用户程序就可用此FILE指针来 ...
- linux快速清空文件 比如log日志
linux中快速清空文件内容的几种方法这篇文章主要介绍了linux中快速清空文件内容的几种方法,需要的朋友可以参考下 权限要求: 至少执行用户对该文件有写的权限 --w------- 1 QA_Dep ...
- Nginx日志配置及配置调试
防火墙内的内网服务器,因为网关传过来的remot_addr都一样,不得不对Nginx的日志格式做了配置 配置语法如下: log_format myformat '$http_x_forwarded ...
- hadoop配置文件详解系列(二)-hdfs-site.xml篇
上一篇介绍了core-site.xml的配置,本篇继续介绍hdfs-site.xml的配置. 属性名称 属性值 描述 hadoop.hdfs.configuration.version 1 配置文件的 ...
- java线程之线程通信控制
在上篇我们看到,A线程往公共资源库(对象)提供了一条数据,然后B线程从库中提取了数据并打印出来. 实际项目中,我们不可能只往库中提供一条数据,而且库的大小也不会是无穷大的,那么我们就会有这样一 个需求 ...
- Beta 冲刺day2
1.昨天的困难,今天解决的进度,以及明天要做的事情 昨天的困难:昨天主要是在确认需求方面花了一些时间,后来终于确认了企业自查风险模块的需求问题 今天解决的进度:根据昨天确认下来的需求,我们基本上完成了 ...
- asp.net路径问题
-------------初级篇---------------------------------------- 在一般的href中路径的引用问题 ./index.aspx与index.aspx都 ...
- win10汇编环境的搭建
第一步:下载DOSBox0.74-win32-installer 可以去官网:http://www.dosbox.com/ 或者链接:https://pan.baidu.com/s/1UA77qTLO ...
- 关于overfit的随笔
看到@ 爱可可-爱生活转发的文章.稍微看了下,在这里记录下. overfit是机器学习的一个重要概念.在狭义上可以定义为模型过于复杂,导致模型的generalization不够好.我认为应采用一个更广 ...