10.13考试总结

来源:互联网 发布:网络电影 罪恶片 编辑:程序博客网 时间:2024/06/07 21:12

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

原创粉丝点击