10.13考试总结

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还是挺惊喜的,这说明暴力也是需要认真写的,你以为你正解写不对但暴力还是可以水过的,其实你会发现你暴力都写不对。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值