How to AK ABC240
__vector__ · · 个人记录
A - Edge Checker
题目大意:
1 到 10 按顺序组成一个环(1 和 10 首尾连接)
给定两个数,问是否相邻。
题目分析:
签到题不需要分析。
\color{green}\text{AC代码:}
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a,b;
cin>>a>>b;
if((a==1&&b==10)||(a==10&&b==1))
{
cout<<"Yes";
return 0;
}
if(abs(a-b)<=1)cout<<"Yes";
else cout<<"No";
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}
B - Count Distinct Integers
题目大意:
给定一个长度为
题目分析:
签到题不需要分析。
\color{green}\text{AC代码:}
#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
int a[maxn];
map<int,int> im;
int main()
{
int n;
cin>>n;
int ans=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(!im[a[i]])ans++;
im[a[i]]=1;
}
cout<<ans;
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}
C - Jumping Takahashi
题目大意:
某人的起始坐标为0(向左为负向右为正)。给定两个长度为
题目分析:
由于本人太菜,只会
首先,朴素的爆搜肯定大家都会写,但是
剪枝一:如果当前搜到的数总和超过了
剪枝二:如果当前搜到的数字总和,后面即使每次都选最大的数,总和仍然比
剪枝三:如果当前搜到的数字总和,后面即使每次都选最小的数,总和仍然比
可见剪枝效果显著,但是仍然无法通过此题。
怎么办?
为了 AC,我加了一个错误的剪枝:
如果递归超过 2000万次还没有搜到结果,那么有解的可能很小(随机数据下),那么直接输出 No。
但是这个是错的,我自己就能 hack 掉。但是 At 的数据太水了所以过了。
正确做法我看完官方题解再放上来。
(还好不是 CF 赛制)
\color{red}\text{错误} \color{blue}\text{但是} \color{green}\text{AC的代码:}
#include <bits/stdc++.h>
using namespace std;
const int maxn=105;
int a[maxn];
int b[maxn];
int qzh[maxn];
int qzh2[maxn];
int n,x;
int cnt=0;
bool dfs(int i,int col)
{
if(++cnt>=20000000)return 0;
// cout<<"i: "<<i<<" col"<<col<<endl;
if(col==x&&i==n+1)return 1;
if(i==n+1)return 0;
if(col>x)return 0;
// cout<<"qzh"<< qzh[n]-qzh[i]<<endl;
// cout<<"qzh"<< qzh2[n]-qzh2[i]<<endl;
//cout<<col+(qzh[n]-qzh[i])<<endl;
//cout<<col+(qzh2[n]-qzh2[i])<<endl;
if(col+(qzh[n]-qzh[i])>x)return 0;
if(col+(qzh2[n]-qzh2[i])<x)return 0;
// cout<<"i: "<<i<<endl;
if(dfs(i+1,col+a[i+1]))return 1;
if(dfs(i+1,col+b[i+1]))return 1;
return 0;
}
int main()
{
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
qzh[i]=qzh[i-1]+min(a[i],b[i]);
qzh2[i]=qzh2[i-1]+max(a[i],b[i]);
}
if(dfs(1,a[1])||dfs(1,b[1]))cout<<"Yes";
else cout<<"No";
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}
D - Strange Balls
题目大意:
有
这些球按照顺序从第
问每放入一个球之后瓶子里有多少球。
题目分析:
可以创建一个栈
插入一个球之后,如果这个球数值与栈顶节点不一样,那么新建一个节点插入栈顶。如果一样,那么栈顶节点
\color{green}\text{AC代码:}
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int n;
int a[maxn];
int top;
struct Sta
{
int size;
int val;
}sta[maxn];
int ans=0;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
if(a[i]!=sta[top].val)
{
sta[++top]={1,a[i]};
ans++;
printf("%d\n",ans);
}
else
{
sta[top].size++;
ans++;
if(sta[top].size==a[i])
{
ans-=sta[top].size;
top--;
}
printf("%d\n",ans);
}
}
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}
E - Ranges on Tree
题目大意:
给定一棵树。树上的每个点都有两个值
设第
每个点的值应满足一下要求:
一、如果点
二、如果点
对每个节点安排它的
题目分析
大力 dfs!
首先确定叶子节点的值,然后,每个节点的 father 节点的值也就是
注:
如何确定叶子结点的值呢?
定义一个变量
对于搜到的每个点首先把这个点的
这样就完成了。
\color{green}\text{AC代码:}
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int head[maxn<<1];
struct EDGE
{
int to,nxt;
}edge[maxn<<1];
int tot;
inline void add(int u,int to)
{
edge[++tot].to=to;
edge[tot].nxt=head[u];
head[u]=tot;
}
int n;
int rd[maxn];//存储入度
struct Val
{
int l,r;
}val[maxn];//存储每个点的取值范围
int dbg;
bool vis[maxn];
int sum=1;
void dfs(int u)
{
val[u].l=sum;
vis[u]=1;
bool flag=0;
//因为如果当前点有子树的话
//统计答案会多统计1
//在此需要标明以来
//减去这个误差
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(vis[to])continue;
if(flag)sum++;
flag|=1;
dfs(to);
}
val[u].r=sum;
}
int main()
{
scanf("%d",&n);
int ut,vt;
for(int i=1;i<n;i++)
{
scanf("%d%d",&ut,&vt);
add(ut,vt);
add(vt,ut);
rd[ut]++;
rd[vt]++;
}
dfs(1);
for(int i=1;i<=n;i++)
{
printf("%d %d\n",val[i].l,val[i].r);
}
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}