AcWing 105.七夕祭

题目描述

七夕节因牛郎织女的传说而被扣上了「情人节」的帽子。

于是TYVJ今年举办了一次线下七夕祭。

Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩。

TYVJ七夕祭和11区的夏祭的形式很像。

矩形的祭典会场由N排M列共计N×M个摊点组成。

虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧、苹果糖、棉花糖、射的屋……什么的。

Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地布置会场,使得各行中cl感兴趣的摊点数一样多,并且各列中cl感兴趣的摊点数也一样多。

不过zhq告诉Vani,摊点已经随意布置完毕了,如果想满足cl的要求,唯一的调整方式就是交换两个相邻的摊点。

两个摊点相邻,当且仅当他们处在同一行或者同一列的相邻位置上。

由于zhq率领的TYVJ开发小组成功地扭曲了空间,每一行或每一列的第一个位置和最后一个位置也算作相邻。

现在Vani想知道他的两个要求最多能满足多少个。

在此前提下,至少需要交换多少次摊点。

输入格式

第一行包含三个整数N和M和T,T表示cl对多少个摊点感兴趣。

接下来T行,每行两个整数x, y,表示cl对处在第x行第y列的摊点感兴趣。

输出格式

首先输出一个字符串。

如果能满足Vani的全部两个要求,输出both;

如果通过调整只能使得各行中cl感兴趣的摊点数一样多,输出row;

如果只能使各列中cl感兴趣的摊点数一样多,输出column;

如果均不能满足,输出impossible。

如果输出的字符串不是impossible, 接下来输出最小交换次数,与字符串之间用一个空格隔开。

数据范围

1≤N,M≤100000
,
0≤T≤min(N?M,100000)
,
1≤x≤N
,
1≤y≤M

样例

输入样例:

2 3 4
1 3
2 1
2 2
2 3
输出样例:

row 1


思路在代码里面

C++ 代码

#include <bits/stdc++.h>
using namespace std;
/**
 首先先考虑不是环的情况下
 那么就是普通的均匀分牌问题
 那么最少次数就是互相给牌
 if(hang[i] < t / n)
 hang[i + 1] -= (t / n - hang[i]), hang[i] += (t / n - hang[i]);
 else
 hang[i + 1] += (hang[i] - t / n), hang[i] -= (hang[i] - t / n);
 (假设hang数组内的值不发生变化,注意不要从0开始,数据是从1开始的,哭了)
 第一种情况下的状态
 hang[1] = hang[1] - (t / n - hang[0]) = hang[1] + hang[0] - t / n;
 第二种情况下的状态
 hang[1] = hang[1] + (hang[0] - t / n) = hang[1] + hang[0] - t / n; 

 第一次的移动次数为abs(t / n - hang[0]);
 第二次的移动次数为abs(t / n - hang[1] - hang[0] + t / n);
                   abs(2 * t / n - (hang[1] + hang[0]));
 所以可得第i次移动的次数为abs(i * t / n - sum(hang[i - 1]));
        那么可以拆分成abs((t / n - hang[0]) + (t / n - hang[1]) + ...... + (t / n - hang[i]));
        预先处理将数组变成 t / n - hang[i]
        那么求一个前缀和就可以得到每次移动的步数

 如果是环形的话,存在相邻的交换给的话
 肯定不是最优解,最优解肯定只存在于不互相给的情况下
 因为比如a b c d e 是个环 a -> c b -> e,那么实际上
 这肯定不是最优解
 因为可以通过b -> c , a -> e来构造一个更优秀的答案
 所以最优解只存在于不互相给的情况下
 那么就选择一个不交换的点,将其转换成普通的均匀分牌问题
 那么就重新选择出了一个非环的序列
 那么如何选择这个不交换的点
 假设该点为k
 取k为原点
 那么k就变成了基点,那么我们先求出了全部的sum[i]的值
 k ~ n
 sum[k + 1] - sum[k]
 sum[k + 2] - sum[k + 1]
 ....
 过了n之后,因为过了n后,sum[0] + sum[n] - sum[k]
 构成了新的序列的前缀和
 sum[n] + sum[0] - sum[k]
 sum[n] + sum[k] - sum[k]

 那么我们要寻找一个合适的k值
 因为sum[n] + sum[0] - sum[k] or sum[k + 1] - sum[k]
 就是一维上的一个求距离的公式
 那么结论就是 取sum[k]的值为sum[1 ~ n]中的中位数
 **/
typedef long long ll;
const int MAXN = 100000 + 5;
int hang[MAXN];
int lie[MAXN];
ll hang_sum[MAXN];
ll lie_sum[MAXN];
struct NODE
{
    ll num;
    ll sum;
};
bool cmp(const NODE &a, const NODE &b)
{
    return a.sum < b.sum;
}
int n, m, t;
void Init()
{
    memset(hang, 0, sizeof(hang));
    memset(lie, 0, sizeof(lie));
    memset(hang_sum, 0, sizeof(hang_sum));
    memset(lie_sum, 0, sizeof(lie_sum));
}
void ycl()
{
    for(int i = 1; i <= n; i ++)
    {
        hang[i] = hang[i] - t / n;
    }
    for(int i = 1; i <= m; i ++)
    {
        lie[i] = lie[i] - t / m;
    }
    hang_sum[0] = hang[0];
    for(int i = 1; i <= n; i ++)
    {
        hang_sum[i] = hang_sum[i - 1] + hang[i];
    }
    lie_sum[0] = lie[0];
    for(int i = 1; i <= m; i ++)
    {
        lie_sum[i] = lie_sum[i - 1] + lie[i];
    }
}
pair<ll, ll> hang_acfinds()
{
    vector<NODE>vec;
    vec.clear();
    for(int i = 1; i <= n; i ++)
        {
            NODE temp;
            temp.num = i;
            temp.sum = hang_sum[i];
            vec.push_back(temp);
        }
    sort(vec.begin(), vec.end(), cmp);
    return {vec[vec.size() / 2].num, vec[vec.size() / 2].sum};
}
pair<ll, ll> lie_acfinds()
{
    vector<NODE>vec;
    vec.clear();
    for(int i = 1; i <= m; i ++)
        {
            NODE temp;
            temp.num = i;
            temp.sum = lie_sum[i];
            vec.push_back(temp);
        }
    sort(vec.begin(), vec.end(), cmp);
    return {vec[vec.size() / 2].num, vec[vec.size() / 2].sum};
}
ll result_hang(pair<ll, ll> num)
{
    ll re = 0;
    for(int i = 1; i <= num.first; i ++)
        re += abs(hang_sum[i] + hang_sum[n] - num.second);
    for(int i = num.first + 1; i <= n; i ++)
        re += abs(hang_sum[i] - num.second);
    return re;
}
ll result_lie(pair<ll, ll> num)
{
    ll re = 0;
    for(int i = 1; i <= num.first; i ++)
        re += abs(lie_sum[i] + lie_sum[m] - num.second);
    for(int i = num.first + 1; i <= m; i ++)
        re += abs(lie_sum[i] - num.second);
    return re;
}
int main()
{
    while(~scanf("%d%d%d", &n, &m, &t))
    {
        Init();
        for(int i = 0; i < t; i ++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            hang[a] ++;
            lie[b] ++;
        }
        bool flag1, flag2;
        flag1 = flag2 = false;
        ycl();
        ll re1, re2;
        if(t % n == 0)///在行的情况下,t个能被整除,才存在解
        {
            flag1 = true;
            pair<ll, ll>num;
            num = hang_acfinds();
            re1 = result_hang(num);
        }
        if(t % m == 0)
        {
            flag2 = true;
            pair<ll, ll>num;
            num = lie_acfinds();
            re2 = result_lie(num);
        }
        if(flag1 && flag2)
        {
            printf("both %lld\n",re1 + re2);
        }
        else if(flag1)
        {
            printf("row %lld\n", re1);
        }
        else if(flag2)
        {
            printf("column %lld\n", re2);
        }
        else
        {
            printf("impossible\n");
        }
    }
    return 0;
}


AcWing 105.七夕祭

原文地址:https://www.cnblogs.com/qq136155330/p/10486885.html

时间: 2024-10-08 06:21:29

AcWing 105.七夕祭的相关文章

[Poetize II]七夕祭

描述 Description TYVJ七夕祭和11区的夏祭的形式很像.矩 形的祭典会场由N排M列共计N×M个摊点组成.虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧.苹果糖.棉花糖.射的屋……什么的. Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地布置会场,使得各行中cl感兴趣的摊点数一样多,并且各列中cl感兴趣的摊点数也一样多.    不 过zhq告诉Vani,摊点已经随意布置完毕了,如果想满足cl的要求,唯一的调整方式就是交换两个相邻的摊点.两个摊点相邻,当且仅

基本算法- 七夕祭

题目描述 七夕节因牛郎织女的传说而被扣上了「情人节」的帽子.于是TYVJ今年举办了一次线下七夕祭.Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩. TYVJ七夕祭和11区的夏祭的形式很像.矩形的祭典会场由N排M列共计N×M个摊点组成.虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧.苹果糖.棉花糖.射的屋--什么的.Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地布置会场,使得各行中cl感兴趣的摊点数一样多,并且各列中cl感兴趣的摊

CODEVS 2485 七夕祭 - 贪心+中位数【环形均分纸牌问题】

CODEVS 2485 七夕祭 Sol: 当行的平均值不为整数时,不能均分,列同理. 对行和列分别做一次环形均分纸牌问题. AC CODE: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100000 + 100; int read(){ int x=0,f=1;char ch=' '; while(ch>'9'||ch<'0

:七夕祭 (货仓选址+均分纸牌)

问题 : 七夕祭 时间限制: 1 Sec  内存限制: 128 MB 题目描述 七夕节因牛郎织女的传说而被扣上了「情人节」的帽子.于是TYVJ今年举办了一次线下七夕祭.Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩. TYVJ七夕祭和11区的夏祭的形式很像.矩形的祭典会场由N排M列共计N×M个摊点组成.虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧.苹果糖.棉花糖.射的屋--什么的.Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地

bzoj3032 七夕祭题解

题面 TYVJ七夕祭和11区的夏祭的形式很像.矩形的祭典会场由N排M列共计N×M个摊点组成.虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧.苹果糖.棉花糖.射的屋--什么的.Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地布置会场,使得各行中cl感兴趣的摊点数一样多,并且各列中cl感兴趣的摊点数也一样多. 不过zhq告诉Vani,摊点已经随意布置完毕了,如果想满足cl的要求,唯一的调整方式就是交换两个相邻的摊点.两个摊点相邻,当且仅当他们处在同一行或者同一列的相邻位置

[bzoj3032][TYVJ P1924]七夕祭(环形均分纸牌,货仓选址)

题意 七夕节因牛郎织女的传说而被扣上了「情人节」的帽子. 于是TYVJ今年举办了一次线下七夕祭. Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩. TYVJ七夕祭和11区的夏祭的形式很像. 矩形的祭典会场由N排M列共计N×M个摊点组成. 虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧.苹果糖.棉花糖.射的屋--什么的. Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地布置会场,使得各行中cl感兴趣的摊点数一样多,并且各列中cl感兴

Lydsy3032 七夕祭(货仓选址+均分纸牌结合)

环形均分纸牌 #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const int maxn=100000+10; ll heng[maxn],shu[maxn]; ll sum[maxn]; ll getans(ll a[maxn],int n){ ll k=a[0]/n; for (int i=1;i<=n;i++){

习题:七夕祭(杂题)

题目 思路 首先一点如果是impossible,那么一定 \(T\%N\)和\(T\%M\)都不为0 再接着, 因为竖着满足跟横着满足本质上是一样的,所以这里只讨论横着满足 并且如果要满足横着的情况, 如果要步数最小,那么我们一定不会将竖着的摊位交换 同理,如果要满足竖着的情况,我们一定不会将横着的摊位交换 也就是说如果我们定义两个数组row和col来维护每一行和每一列的摊位个数 那么竖着交换对col数组没有任何影响,横着交换对row数组也没有任何影响 也就是指,如果是both的话, 我们只需要

七夕祭(贪心+中位数)

传送门 思路 因为交换同一列的相邻两行,这一列的总数不变:交换同一行的相邻两列,这一行的总数不变. 那么如果可以平均分配的话,可以先将所有行都分配好,然后再将所有列分配好. 这样就变成了做两次环形纸牌分配问题, 给一个数列,最后一位和第一位相邻,问能否平均分配,最少需要传递多少次. 首先考虑普通纸牌均分问题: 有 \(n\) 个人坐成一排,每个人 \(a[i]\) 张牌,每个人只能和旁边的人交换纸牌,问最好交换几次能使所有人的手牌数相等. 这是一个经典问题,答案等于 \(\sum_{i=1}^n