—>XJOI奋斗群(蒻蒟群)群赛10<— RANK排名7
T1:Chess Tourney(WA一次后AC)
题意:
给你一个数组,有2*n个元素。让你把这个数组分成两部分,要求不管怎么取这两个数组中的元素,第一部分都要大于第二部分,问是否能够分成这样。
分析过程:
由于是要随机取都必须满足,我们就先把数组从大到小排序,分别取第i(i<=n)个和第2*n-i+1个元素进行比较,如果结果是大于的,就继续,否则输出NO。
给出题解:
#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int n,ans;
int a[205];
int cnt=0;
cin>>n;
for(int i=1;i<=2*n;i++)cin>>a[i];
sort(a+1,a+1+2*n,cmp);
// for(int i=1;i<=2*n;i++)cout<<a[i]<<" ";
for(int i=1;i<=2*n;i++)
{
if(a[i]>a[2*n+1-i])
{
cnt++;
}
if(cnt==n)
{
cout<<"YES"<<endl;
return 0;
}
}
// cout<<cnt<<endl;
cout<<"NO"<<endl;
return 0;
}
T2:Luba And The Ticket(WA两次后AC)
题意:
有一个长度为6的数字串,要求你改变这里面的任意几个数字,让它的前三位和后三位加起来的和相同。求最少改变的数字个数
分析过程:
先计算数字串前三个与后三个的和是否相等,如果不相等,就把较小的字符串从小到大排序,计算每个数字与9的差(这个值就是这个数字改变之后能够使数字串的和增加的值)。然后用原来的和加上这些值,一旦和大于等于另三个数字的和,那么就break,输出加上数字的个数。
给出题解:
#include<bits/stdc++.h>
using namespace std;
int n,b,a[10],sum;
char c;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
for(int i=1;i<=6;i++)
{
cin>>c;
a[i]=c;
a[i]-='0';
}
b=a[1]+a[2]+a[3]-a[4]-a[5]-a[6];
if(b!=0)
{
int i=0;
if(b>0)
{
a[4]=9-a[4];a[5]=9-a[5];a[6]=9-a[6];
sort(a+1,a+7,cmp);
while(sum<b)
{
i++;
sum+=a[i];
}
}
else
{
b=-b;
a[1]=9-a[1];a[2]=9-a[2];a[3]=9-a[3];
sort(a+1,a+7,cmp);
while(sum<b)
{
i++;
sum+=a[i];
}
}
cout<<i;
}
else cout<<0;;
return 0;
}
T3:Two TVs (WA一次后AC)
题意:
简单来说,就是给你一棵树,让你把这颗树分成3段,每段的所有节点的和都相等。让你求是否有这种方案。如果有,就输出切割的点,如果没有就输出-1。
分析过程:
这题可以不用建树,用邻接表也同样可以做出来。只要从一个叶子节点向上遍历,搜索到这个节点的和路径上的所有点的和达到一定值就记录该节点,并将ans归零,继续搜索。如果搜索完之后只搜索到一个切割的带你,就输出-1,否则输出切割的两个点。
给出题解:
#include<bits/stdc++.h>
#define maxn 1000050
using namespace std;
int n,sum,l,tem[maxn],ans,x=0,f[maxn],cut=0,node,cut1;
struct tree
{
int next;
int to;
}a[maxn];
void add(int c,int d)
{
x++;
a[x].to=d;
a[x].next=f[c];
f[c]=x;
}
void dfs(int c)
{
int d=c;
c=f[c];
while(c!=-1)
{
dfs(a[c].to);
tem[d]+=tem[a[c].to];
c=a[c].next;
// cout<<tem[d]<<endl;
}
if(tem[d]==ans&&d!=node)
{
if(cut==0)
{
cut++;
tem[d]=0;
cut1=d;
}
else
{
cut++;
cout<<cut1<<" "<<d;
exit(0);
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
memset(f,-1,sizeof(f));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&l,&tem[i]);
if(l!=0)
add(l,i);
if(l==0)
node=i;
ans+=tem[i];
}
// cout<<"node="<<node<<endl;
if(ans%3!=0)
{
printf("-1\n");
exit(0);
}
else ans=ans/3;
dfs(node);
// cout<<cut<<endl;
if(cut!=2)
{
printf("-1\n");
exit(0);
}
}
T4:Driving Test (WA六次之后AC)
题意:
一个人要去考驾照,考试时有四种指示,分别是限速,允许超车,不限速,不允许超车。这个人在考试时会有6种操作,分别为变速(1),超车(2),经过限速牌(3),经过允许超车牌(4),经过不限速牌(5),经过不允许超车牌(6)。这个人在考试时可能会违反几次交通规则,问这个人得说他忽视了多少交通指示牌才能通过考试。
分析过程:
先设这个人需要忽视的牌子的个数为cnt。对于违反了几次超车的牌子比较简单,只要设一个overtake,每经过一个不允许超车的牌子就++,如果经过一个允许超车的牌子就清零,如果在不允许超车的路段,这个人超车了,就用cnt+overtake,并把overtake清零。但对于限速就可以用栈了。如果遇到限速牌,就把限速牌入栈。如果遇到变速牌,就把栈中元素一个一个出栈,如果栈顶元素的speed值大于当前的速度,就可以直接出栈,反之,就cnt++后出栈,最后输出cnt的值。
给出题解:
#include<bits/stdc++.h>
using namespace std;
#define inf 5000
int sign,change,limit;
int overtake=0;
int speed=inf;
int main()
{
stack<int >q;
long long n;
cin>>n;
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&sign);
if(sign==1)
{
scanf("%d",&change);
speed=change;
while(q.empty()==false&&q.top()<speed)
{
q.pop();
cnt++;
}
}
if(sign==2)
{
cnt+=overtake;
overtake=0;
}
if(sign==3)
{
scanf("%d",&limit);
q.push(limit);
while(q.empty()==false&&q.top()<speed)
{
q.pop();
cnt++;
}
}
if(sign==4)
{
overtake=0;
}
if(sign==5)
{
while(q.empty()==false)
{
q.pop();
}
}
if(sign==6)
{
overtake++;
}
}
cout<<cnt<<endl;
}
T5:Fire in the City
题意:
分析过程:
给出题解:
T6:Guards In The Storehouse
题意:
分析过程:
给出题解:
T7:Shortest Path Problem?
题意:
分析过程:
给出题解:
蒻蒟的总结:
再一次补发昨天的微博,真的是好难啊,果然啊,几个月达到别人几年的效果,真的是很艰难的一段路啊。不过还是能够坚持下去的,明天就是短暂的周末了,也要好好利用起来,今天晚上继续理解KMP,DP,树和队列,明天凌晨在去做一场比赛,先把CF上的分刷出来再说,最后再把这几天没补的题目补好。好好利用每个周末,这些都是宝贵的时间,顺便休整一下。
继续贴出吴老师的话:学信息的人永不服输!!!