codeforces 1260 总结

A
给两个值a,b,a<=b;把b拆成a个数,求这a个数的平方和的最小值。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
    int n;
    int a,b;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d",&a,&b);
        int t=b/a;
        int tt=b%a;
        int ans=0;
        ans=t*t*(a-tt)+(t+1)*(t+1)*tt;
        printf("%d\n",ans);
    }
    return 0;
}

B
给两个数a,b,每次可以进行a-x,b-2x,或a-2x,b-x,这里x为任意正整数。问能否使得 a=0,b=0;
思路:a+b=k3x;
a<=2kx;a>=k*x;

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
   int t;
   scanf("%d",&t);
   int a,b;
   int sum;
   while(t--)
   {
       scanf("%d%d",&a,&b);
      sum=a+b;
      if(sum%3==0)
      {
          if(a>b) swap(a,b);
          if(a>=sum/3&&a<=sum/3*2) printf("YES\n");
          else printf("NO\n");
      }
      else printf("NO\n");

   }
   return 0;
}

C
给三个数,a,b,c;其中a<=b;
求(k-1)b与kb之间的能够被a整除的数的个数的最大值是否小于c。

思路:刚开始以为只要找出b,与2b之间的个数就行,但是,有可能不对,
欧几里得法 k1b+a的倍数在相邻两个b的倍数之间的初始位置=k2a;
那么若成立,则gcd(a,b)|初始位置,使初始值尽量靠前,则初始位置=gcd(a,b);

注:__gcd()在c++14以上支持。

#include <bits/stdc++.h>
using namespace std;
int main()
{
   ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    int r,b,k;
    while(n--)
    {
        cin>>r>>b>>k;
        if(r>b) swap(r,b);
        int tt=(b-__gcd(r,b)-1)/r+1;
        if(tt<k) cout<<"OBEY"<<endl;
        else cout<<"REBEL"<<endl;
    }
    return 0;
}


D
给你n个人,每个人的值为ai,给出k个陷阱,每个陷阱由三个值描述,陷阱位置 ,解除该陷阱位置,后者大于前者,陷阱伤害值,你每次移动一格耗时一秒,你的人经过没有解除的陷阱时,若你的人的值小于该陷阱的伤害值,那么你的人就会死,你不受陷阱影响,你的人移动时你必须在你的人身边,给出t秒的时间限制,求在规定时间内你最多能将你的多少人从0位置运输到n+1位置。

思路:二分人的值,求出比mid值大的人要运送过去所需时间,将这个时间与总时间比较,进而确定二分区间。
在求时间时需要对陷阱位置导致的不同情况分类讨论。

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<utility>
using namespace std;
int m,n,k,t;
int a[200005];
int l[200005],r[200005],d[200005];
bool jud(int mid)
{
    int tt=a[mid];
    vector<pair<int,int>> v;
    for(int i=1;i<=k;i++)
    {
        if(d[i]>tt)
        {
            v.push_back(make_pair(l[i],r[i]));
        }
    }
    sort(v.begin(),v.end());
    int sum=n+1;
    int compared=0;
    vector<pair<int,int>>::iterator it;
    pair<int,int>to;
    for(it=v.begin();it!=v.end();it++)
    {
        to=(*it);
        if(to.first<=compared)
        {
            sum=sum+2*max(0,to.second-compared);
            compared=max(compared,to.second);
        }
        else
        {
            sum=sum+(to.second-to.first+1)*2;
            compared=to.second;
        }
    }
    return sum<=t;
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>m>>n>>k>>t;
   for(int i=1;i<=m;i++)
   {
       cin>>a[i];
   }
   sort(a+1,a+1+m);
   for(int i=1;i<=k;i++)
   {
       cin>>l[i]>>r[i]>>d[i];
   }
   int le=1,ri=m;
   int mid;
   int ans=0;
   while(le<=ri)
   {
       mid=(le+ri)>>1;
       if(jud(mid))
       {
           ans=m-mid+1;
           ri=mid-1;
       }
       else le=mid+1;
   }
   cout<<ans<<endl;
   return 0;
}

E
n个人打拳击,力量分别值为1,2,3…n,两两比赛,8进4,4进2赛制,你可以安排谁和谁比,每个人有一个贿赂值,花费这个值可以让这个人认输,求确保其中指定的一个人赢得最小花费。

思路:若这个人为最强,不用花钱,若这个人为中上等水平,至少有一场要花钱,中下等水平的中上等,有两场要花钱,结合优先队列,求出和值。

#include <iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int N=(1<<18)+5;
int a[N];
int main()
{
    priority_queue<int,vector<int>,greater<int> >q;
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    ll ans=0;
    int i;
    while(n>1)
    {
        if(a[n-1]==-1) break;
        q.push(a[n-1]);
        ans+=q.top();
        q.pop();
        for( i=n-2;i>=n>>1;i--)
        {
            if(a[i]==-1) break;
            q.push(a[i]);
        }
        if(i>=n>>1) break;
        n=n>>1;
    }
    printf("%lld\n",ans);
}

有关判断一个整数x是否是2的N次方的文章链接(x & (x - 1)==0)
https://blog.csdn.net/xindoo/article/details/8578999

F
节点为n的树,每个节点都有一个颜色,定义一个值为树上任意两个颜色一样的点的最小路径的长度之和。
但是,每个点的颜色忘记了,只记得属于区间(l,r);
求出所有可能的情况下的这个值的和最后mod 1e9+7;

思路: 额》》。。。。。。。。。,感觉和之间学的线段树有关系。。。。。。。。。 ,然后蒙。。。
查了查题解,哎,之前的线段树就学的不咋的,结果又来了一个树剖分析。。。。。。。 只明白了一部分,有关树的知识需要回顾,树剖啥的要好好学学。

总结: 今天突然发现之前学的二叉树,线段树,树状数组啥的基本上都忘了,要好好回顾。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值