codeforces 459 (div 2) 题解

本文深入探讨了算法和数据结构的基础知识,包括排序算法、动态规划、哈希算法、贪心算法、深度优先搜索、近邻算法、霍夫曼树、电梯算法、遗传算法、广度优先搜索等。同时,文章还涵盖了数据结构如二叉树、队列、栈、数组、链表、B树、散列表等。此外,文章还涉及了非IT技术、自动推理、人工神经网络与计算等领域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

    给你一个矩形的两个顶点,让你求另外两个顶点。

解题思路:

   水题不解释了

我的代码:

#include <cstdio>
using namespace std;
int main (){
  int x1,y1,x2,y2;
  while (~scanf("%d%d%d%d",&x1,&y1,&x2,&y2)){
    int x3,y3,x4,y4;
    bool yes=true;
    if (x1==x2&&y1!=y2){
       int c=y1-y2;
       if (c<0) c=-c;
       if (x1+c>1000) x3=x4=x1-c;
       else x3=x4=x1+c;
       y3=y1;y4=y2;
    }
    if (x1!=x2&&y1==y2){
        int c=x1-x2;
        if (c<0)c=-c;
        if (y1+c>1000) y3=y4=y1-c;
        else y3=y4=y1+c;
        x3=x1;x4=x2;
    }
    if (x1!=x2&&y1!=y2){
        int c=x1-x2;
        int d=y1-y2;
        if (c<0) c=-c;
        if (d<0) d=-d;
        if (c!=d) printf("-1\n"),yes=false;
        else {
           x3=x1;y3=y2;
           x4=x2;y4=y1;
        }
    }
    if (yes){
        printf("%d %d %d %d\n",x3,y3,x4,y4);
    }
  }
  return 0;
}
B.

题目大意:

   给你n个数,取两个数使得两个数之差最大,问最大差为多少,有几种取法。

解题思路:

   水题不解释,但是注意最大值超出int 要使用longlong

我的代码:

#include <cstdio>
#include <iostream>
using namespace std;
long long minx,x,maxn,y;
int n;
int main (){
  while (~scanf("%d",&n)){
    for (int i=0;i<n;i++){
      long long c;cin>>c;
      if (i==0){
        minx=maxn=c;
        x=y=1;
      }
      else {
        if (c==maxn) x++;
        else if (c>maxn){
          maxn=c;x=1;
        }
        if (c==minx) y++;
        else if (c<minx) {
          minx=c;y=1;
        }
      }
    }
    if (maxn==minx){
       long long kkk=(long long)n*(n-1)/2;
       printf("%I64d %I64d\n",maxn-minx,kkk);
    }
    else printf("%I64d %I64d\n",maxn-minx,x*y);
  }
  return 0;
}

C.

题目大意:

  n个人做k辆车出去玩d天,求出一种坐车方式使得n个人,任意两个人这d天坐车方式都不完全一样。(完全一样就是这d天,每天都坐同一辆车)。

解题思路:

  先假设最后一天每个人坐的车都不一样,当然k>=n时这种情况才满足。

  如果k<n的时候,我们就让最后一天的车编号对k取模,倒数第二天就是最后一天的车编号除以k。(车的编号从0开始)

  倒数第二天操作与倒数第一天一样。(有点类似k进制运算)

  最后得到的矩阵中如果有数大于等于k,就表示不可能,否则输出矩阵。

我的代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define maxn 1010
using namespace std;
int a[maxn][maxn];
int main (){
  int n,k,d;
  while (~scanf("%d%d%d",&n,&k,&d)){
    memset(a,0,sizeof(a));
    for (int i=0;i<n;i++)
       a[d-1][i]=i;
    for (int i=d-1;i>0;i--){
        for (int j=0;j<n;j++){
            a[i-1][j]+=a[i][j]/k;
            a[i][j]%=k;
        }
    }
    int yes=true;
    for (int i=0;i<d;i++)
        for (int j=0;j<n;j++)
          if (a[i][j]>=k) {
                printf("-1\n"),yes=false;
                break;
          }
    if (yes){
        for (int i=0;i<d;i++)
            for (int j=0;j<n;j++)
              printf("%d%c",a[i][j]+1,j==n-1?'\n':' ');
    }

  }
  return 0;
}

D

题目大意:

  给你n个数,规定两个函数f(x),g(x),f(x)为1到x这些数中与ax相等数的个数,g(x)为为x到n这些数中与ax相等数的个数。

  问你存在多少组(x,y) f(x)>g(y)。

解题方法:

  f(x),g(x)按照一般方法求就可以了。

  但是最后求多少组的时候要使用树状数组,否则会TLE。

  是树状数组的简单应用。

我的代码:

#include <cstdio>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
map <int ,int >vis;
int num[1000010],a[1000010],b[1000010];
int n;
int tree[1000010];
int add(int x,int v){
  for (int i=x;i<1000000;i+=i&(-i))
    tree[i]+=v;
  return 0;
}
int sum(int x){
  if (x==0) return 0;
  int ans=0;
  for (int i=x;i>0;i-=i&(-i))
    ans+=tree[i];
  return ans;
}
int main (){
  //freopen("test.in","r",stdin);
  while (~scanf("%d",&n)){
    vis.clear();
    for (int i=0;i<n;i++){
        scanf("%d",&num[i]);
        vis[num[i]]++;
        a[i]=vis[num[i]];
    }
    vis.clear();
    for (int i=n-1;i>=0;i--){
        vis[num[i]]++;
        b[i]=vis[num[i]];
    }
    //for (int i=0;i<n;i++)
    //    cout<<a[i]<<" ";cout<<endl;
    //for (int i=0;i<n;i++)
    //    cout<<b[i]<<" ";cout<<endl;
    long long ans=0;
    memset(tree,0,sizeof(tree));
    for (int i=n-1;i>=0;i--){
        //cout<<a[i]-1<<" "<<sum(a[i]-1)<<endl;
        ans+=sum(a[i]-1);
        add(b[i],1);
    }
    cout<<ans<<endl;
  }
  return 0;
}
E.

题目大意:

  给你m条边,每条边有权重w,让你找到一个最长路线,在这条路线上权重递增,问最长路线的长度。

解题方法:

  先将边从小到大排序,然后就是dp了,dp[i]=max(dp[i],dp[u]) (第i条边 u->v)

我的代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define maxn 300010
using namespace std;
struct edge{
  int x,y,w;
}edg[maxn];
int num[maxn];
int dp[maxn];
int n,m;
int cmp(edge a,edge b){
  return a.w<b.w;
}
int main (){
   //freopen("test.in","r",stdin);
   while (~scanf("%d%d",&n,&m)){
      memset(edg,0,sizeof(edg));
      memset(num,0,sizeof(num));
      memset(dp,0,sizeof(dp));
      for (int i=0;i<m;i++){
        scanf("%d%d%d",&edg[i].x,&edg[i].y,&edg[i].w);
      }
      sort(edg,edg+m,cmp);
      int ans=0,begins=0;
      for (int i=0;i<m;i++){
         dp[i]=num[edg[i].x]+1;
         if (edg[i].w!=edg[i+1].w){
            for (int j=begins;j<=i;j++)
              num[edg[j].y]=max(num[edg[j].y],dp[j]);
            begins=i+1;
         }
         ans=max(ans,dp[i]);
      }
      printf("%d\n",ans);
   }
   return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值