2018 “百度之星”程序设计大赛 - 初赛(B)

degree

 
 Accepts: 1581
 
 Submissions: 3494
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
Problem Description

度度熊最近似乎在研究图论。给定一个有 NN 个点 (vertex) 以及 MM 条边 (edge) 的无向简单图 (undirected simple graph),此图中保证没有任何圈 (cycle) 存在。

现在你可以对此图依序进行以下的操作:

  1. 移除至多 KK 条边。
  2. 在保持此图是没有圈的无向简单图的条件下,自由的添加边至此图中。

请问最后此图中度数 (degree) 最大的点的度数可以多大呢?

Input

输入的第一行有一个正整数 TT,代表接下来有几笔测试资料。

对于每笔测试资料: 第一行有三个整数 NN, MM, KK。 接下来的 MM 行每行有两个整数 aa 及 bb,代表点 aa 及 bb 之间有一条边。 点的编号由 00 开始至 N - 1N1。

  • 0 \le K \le M \le 2 \times 10^50KM2×105​​
  • 1 \le N \le 2 \times 10^51N2×105​​
  • 0 \le a, b < N0a,b<N
  • 给定的图保证是没有圈的简单图
  • 1 \le T \le 231T23
  • 至多 22 笔测试资料中的 N > 1000N>1000
Output

对于每一笔测试资料,请依序各自在一行内输出一个整数,代表按照规定操作后可能出现的最大度数。

Sample Input
2
3 1 1
1 2
8 6 0
1 2
3 1
5 6
4 1
6 4
7 0
Sample Output
2
4

简单图啊, C = V-E

所以就可以这样拆边了,只和度数有关

#include
#include
using namespace std;
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define pb push_back
#define num first
#define id second
#define ll long long
#define sz(x) (int)(x).size()
#define pll pair
#define pii pair
#define pq priority_queue
const int N=2e5+5,MD=1e9+7,INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9,e=exp(1),PI=acos(-1.);
int d[N];
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        memset(d,0,sizeof d);
        int n,m,k;
        cin>>n>>m>>k;
        for(int i=0,x,y;i>x>>y,d[x]++,d[y]++;
        int ans=0;
        for(int i=0;i)
            ans=max(ans,n-1-max(0,m-d[i]-k));
        printf("%d\n",ans);
    }
    return 0;
}

rect

 
 Accepts: 1682
 
 Submissions: 3028
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
Problem Description

度度熊有一个大小为 MX \times MYMX×MY 的矩形,左下角坐标为 (0, 0)(0,0),右上角坐标为 (MX, MY)(MX,MY)。此矩形内有 NN 个整数坐标的点 (x_i, y_i)(xi​​,yi​​),x_ixi​​ 彼此不重复,y_iyi​​ 彼此也不重复。

现在要从每一个点画出一条线段,满足下列条件:

  • 线段起点为坐标点,终点在矩形范围的四个边界之一上。
  • 线段彼此不能交叉。

现在要让画出的线段的长度总和最小,请输出这个最小的长度总和值。

Input

输入的第一行有一个正整数 TT,代表接下来有几笔测试资料。

对于每笔测试资料: 第一行有三个整数 MXMX, MYMY 以及 NN。 接下来的 NN 行每行有两个正整数 x_ixi​​ 及 y_iyi​​。

  • 2 \le MX, MY \le 10^62MX,MY106​​
  • 0 \le N \le 10^50N105​​
  • 如果 i \ne jij,则保证 x_i \ne x_jxi​​xj​​ 及 y_i \ne y_jyi​​yj​​
  • 0 < x_i < MX0<xi​​<MX
  • 0 < y_i < MY0<yi​​<MY
  • 1 \le T \le 201T20
  • 至多 22 笔测试资料中的 N > 1000N>1000
Output

对于每一笔测试资料,请依序各自在一行内输出一个整数,代表可能的最小长度和。

Sample Input
2
4 4 1
2 2
10 7 3
6 3
2 6
9 5
Sample Output
2
5

限制条件比较多,x_ixi​​ 彼此不重复,y_iyi​​ 彼此也不重复。

所以最小值就可以了

#include
#include
using namespace std;
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define pb push_back
#define num first
#define id second
#define ll long long
#define sz(x) (int)(x).size()
#define pll pair
#define pii pair
#define pq priority_queue
const int N=2e5+5,MD=1e9+7,INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9,e=exp(1),PI=acos(-1.);
int d[N];
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        int mx,my,n;
        cin>>mx>>my>>n;
        ll sum=0;
        for(int i=0,x,y; i)
        {
            cin>>x>>y;
            int t=min(x,mx-x);
            t=min(t,y);
            t=min(my-y,t);
            sum+=t;
        }
        cout<"\n";
    }
    return 0;
}

p1m2

 
 Accepts: 1003
 
 Submissions: 4595
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
Problem Description

度度熊很喜欢数组!!

我们称一个整数数组为稳定的,若且唯若其同时符合以下两个条件:

  1. 数组里面的元素都是非负整数。
  2. 数组里面最大的元素跟最小的元素的差值不超过 11。

举例而言,[1, 2, 1, 2][1,2,1,2] 是稳定的,而 [-1, 0, -1][1,0,1] 跟 [1, 2, 3][1,2,3] 都不是。

现在,定义一个在整数数组进行的操作:

  • 选择数组中两个不同的元素 aa 以及 bb,将 aa 减去 22,以及将 bb 加上 11。

举例而言,[1, 2, 3][1,2,3] 经过一次操作后,有可能变为 [-1, 2, 4][1,2,4] 或 [2, 2, 1][2,2,1]。

现在给定一个整数数组,在任意进行操作后,请问在所有可能达到的稳定数组中,拥有最大的『数组中的最小值』的那些数组,此值是多少呢?

Input

输入的第一行有一个正整数 TT,代表接下来有几组测试数据。

对于每组测试数据: 第一行有一个正整数 NN。 接下来的一行有 NN 个非负整数 x_ixi​​,代表给定的数组。

  • 1 \le N \le 3 \times 10^51N3×105​​
  • 0 \le x_i \le 10^80xi​​108​​
  • 1 \le T \le 181T18
  • 至多 11 组测试数据中的 N > 30000N>30000
Output

对于每一组测试数据,请依序各自在一行内输出一个整数,代表可能到达的平衡状态中最大的『数组中的最小值』,如果无法达成平衡状态,则输出 -11。

Sample Input
2
3
1 2 4
2
0 100000000

Sample Output
2
33333333

不是加1和减1,但是其实就是每次把数-1,那么一定可以的啊,不存在-1

所以直接二分ans,因为操作次数越多,一定是可以做到的,我是个啥子,一小心爆了ll,现在我们需要做的就是每个数变到目标数需要进行的操作及操作数

#include
#include
using namespace std;
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define pb push_back
#define num first
#define id second
#define ll long long
#define sz(x) (int)(x).size()
#define pll pair
#define pii pair
#define pq priority_queue
const int N=3e5+5,MD=1e9+7,INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9,e=exp(1),PI=acos(-1.);
int a[N],n;
int la(int x)
{
    ll s1=0,s2=0;
    for(int i=0; i)
    {
        if(a[i]>x+1)s2+=(a[i]-x)/2;
        else s1+=max(0,x-a[i]);
    }
    return s2>=s1;
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=0; i>a[i];
        int l=0,r=1e9,ans=0;
        while(l<=r)
        {
            int mi=(l+r)/2;
            if(la(mi)) ans=mi,l=mi+1;
            else r=mi-1;
        }
        cout<"\n";
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/BobHuang/p/9501508.html

你可能感兴趣的:(2018 “百度之星”程序设计大赛 - 初赛(B))