1.鱼群分裂(100/100)
题目大意:给一n个鱼,他们会不断分裂,每次分裂为两堆不相差超过k,求最终形成的堆数;
感想:其实没什么感想,十分钟的事,拿个堆维护下就好了,不说了吧。
# include <iostream>
# include <string>
# include <cstring>
# include <cmath>
# include <ctime>
# include <cstdio>
# include <vector>
# include <queue>
# include <algorithm>
using namespace std;
typedef long long ll;
int Read()
{
int i=0,f=1;char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {i=i*10+(c-'0'); c=getchar();}
return f*i;
}
int n,k,x,y,ans=1;
int main()
{
n=Read(),k=Read();
queue<int >q;
if(!((n-k)&1)) q.push(n);
else {printf("%d\n",ans);return 0;}
while(!q.empty())
{
ans++;
int nowp=q.front();
q.pop();
x=(nowp+k)/2;
y=(nowp-k)/2;
if(!((x-k)&1)&&x>k) q.push(x);
if(!((y-k)&1)&&y>k) q.push(y);
}
printf("%d\n",ans);
}
2.跑步(0/100)
题目大意:n个人在圆圈上跑步,方向不限,当两个相遇时编号小的淘汰,求多长时间游戏结束;
感想:实在没想到怎么写,然后只有将每个人连边然后暴力判,结果奇迹般的wa了,qaq。好了说正解:计算最近相遇的会是哪两个,然后用链表和优先队列维护一下就好,还不是暴力,只是姿势高超(nlogn)。据学长说还有o(n)的写法,但实在写不来,所以自己钻研吧,若可以告知,非常感谢。
# include <iostream>
# include <string>
# include <cstring>
# include <cmath>
# include <ctime>
# include <cstdio>
# include <vector>
# include <queue>
# include <stack>
# include <algorithm>
using namespace std;
typedef long long ll;
int Read()
{
int i=0,f=1;char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {i=i*10+(c-'0'); c=getchar();}
return f*i;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
int t,n,m,vk,dk,v[100005],l[100005],r[100005];
bool vis[100005]={false};
struct node
{
int id,str;
friend bool operator <(const node &a,const node &b){return a.str<b.str;}
}d[100005];
inline void calc(int i,int j)
{
int x,y;
x=d[i].id;y=d[j].id;
if(d[i].str>d[j].str){
if(v[x]>v[y]) dk=(d[j].str+m-d[i].str),vk=(v[x]-v[y]);
if(v[x]<v[y]) dk=(d[i].str-d[j].str),vk=(v[y]-v[x]);
}
if(d[i].str<d[j].str){
if(v[x]>v[y]) dk=(d[j].str-d[i].str),vk=(v[x]-v[y]);
if(v[x]<v[y]) dk=(d[i].str+m-d[j].str),vk=(v[y]-v[x]);
}
}
struct data
{
int i,j;
data(int i,int j) : i(i),j(j){}
friend bool operator <(const data &a,const data &b)
{
int x1,y1,x2,y2;
calc(a.i,a.j);x1=dk,y1=vk;
calc(b.i,b.j);x2=dk,y2=vk;
return (double)x1/(double)y1>(double)x2/(double)y2;
}
};
int GCD(int a,int b)
{
if(b==0) return a;
return GCD(b,a%b);
}
int main()
{
t=Read();
while(t--)
{
n=Read(),m=Read();
for(int i=1;i<=n;++i)d[i].str=Read(), d[i].id=i;
for(int i=1;i<=n;++i)v[i]=Read();sort(d+1,d+n+1);
for(int i=1;i<=n;++i)
{
if(i==1) l[i]=n;else l[i]=(i-1+n)%n;
if(i==n-1) r[i]=n;else r[i]=(i+1)%n;
}
priority_queue<data >q;
for(int i=1;i<=n;++i)
{
if(i==n-1) q.push(data(i,n));
else q.push(data(i,(i+1)%n));
}
memset(vis,0,sizeof(vis));int a,b;
while(!q.empty())
{
data now=q.top();q.pop();
int i=now.i,j=now.j;
if(vis[i]||vis[j]) continue;
if(d[j].id>d[i].id) swap(i,j);
calc(i,j);a=dk,b=vk;vis[j]=1;
int LL=l[j],RR=r[j];
r[LL]=RR,l[RR]=LL;
if(LL!=i) q.push(data(LL,i));
if(RR!=i) q.push(data(i,RR));
}
int cg=GCD(a,b);
write(a/cg);cout<<"/";write(b/cg);cout<<endl;
}
}
3.拆墙(100/100)
题目大意:给许多封闭区域,现在需要将其打通,使得任意区域可以互相到达,求最小花费;
感想:想了一会,咦,这不就是颗森林吗,于是默默的写了一个最大生成树,然后就A了,没什么好说的,很水。
# include <iostream>
# include <string>
# include <cstring>
# include <cmath>
# include <ctime>
# include <cstdio>
# include <vector>
# include <queue>
# include <algorithm>
using namespace std;
typedef long long ll;
int Read()
{
int i=0,f=1;char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {i=i*10+(c-'0'); c=getchar();}
return f*i;
}
struct node{
int u,v,w;
friend bool operator < (const node &a,const node &b)
{ return a.w>b.w;}
}E[100005<<2];
int n,m,x,y,z,fa[100005];
int getfa(int x){
if(x==fa[x]) return x;
fa[x]=getfa(fa[x]);
return fa[x];
}
int main(){
int t=Read();
while(t--){
n=Read(),m=Read();
for(int i=1;i<=n;++i)
x=Read(),y=Read();
int tot=0,cnt=0;
for(int i=1;i<=m;++i){
E[++cnt].u=Read(),E[cnt].v=Read();
E[cnt].w=Read(); tot+=E[cnt].w;
}
sort(E+1,E+cnt+1);
for(int i=1;i<=n;++i) fa[i]=i;
int t=0,ans=0;
for(int i=1;i<=cnt;++i){
int fx=getfa(E[i].u);
int fy=getfa(E[i].v);
if(fx!=fy){
fa[fy]=fx;
ans+=E[i].w;t++;
}
}
printf("%d %d\n",(cnt-t),(tot-ans));
}
}
总结:本次拿了200分,不过题很水,第二题意外暴0还是挺惊喜的,这说明暴力也是需要认真写的,你以为你正解写不对但暴力还是可以水过的,其实你会发现你暴力都写不对。。。