1921(920div3)

A. Square

给出四个坐标,算出正方形的面积

int _,x[5],y[5];
void solve()
{
    for (int i = 1; i <= 4;i++)
        cin >> x[i] >> y[i];
    sort(x + 1, x + 5);
    sort(y + 1, y + 5);
    cout << (x[4] - x[1]) * (y[4] - y[1]) << '\n';
}

B . Arranging Cats

科学家们有 n 个箱子,猫可以坐在里面,也可以不坐在里面。
盒子的当前状态用序列 b1,,bn 表示:如果 i 号盒子里有猫,则为 bi=1 ,否则为 bi=0

幸运的是,猫可以无限量生产,因此科学家们可以在一天内完成以下操作之一:

我们还发现,有些盒子里马上就装满了猫。因此,科学家们知道猫在盒子中的初始位置 s1,,sn 和期望位置 f1,,fn

指出检验假设所需的最少天数。

对于每组数据:
ns(string)f(string)

Solution

实际上,一对 (0,1)(1,0) 可以相互抵消掉,则答案就是 可以抵消掉的对数 加上 不能抵消掉的对数
可以抵消的个数为 cnt=min(cnt1,cnt2),没有抵消掉的个数为 max(cnt1,cnt2)cnt
总数即为 max(cnt1,cnt2)

string s, f;
void solve()
{
    int n;
    cin >> n;
    cin >> s >> f;
    int cnt1 = 0, cnt2 = 0;
    for (int i = 0; i < n;i++)
    {
        if(s[i]=='0'&&f[i]=='1')
            cnt1++;
        if(s[i]=='1'&&f[i]=='0')
            cnt2++;
    }
    int cnt = min(cnt1, cnt2);
    cout << cnt + (max(cnt1, cnt2) - cnt) << '\n';//cout<<max(cnt1,cnt2)<<'\n';
    //ans = the pair of <1,0>and <0,1>+the differences numbers
}

C . Sending Messages

需要在 m1,m2,mn ( mi<mi+1 ) 时刻发送 n 条信息。
0 时刻,他的手机只剩下 f 单位的电量。在 0 时刻,手机处于开机状态。

每开机一个单位,手机就会损失 a 个单位的电量。
此外,斯捷潘可以随时关闭手机,稍后再打开。这一操作每次消耗 b 个单位的能量。
考虑到开机和关机是瞬时的,因此您可以在 x 时刻开机,并在同一时刻发送信息,反之亦然,在 x 时刻发送信息,并在同一时刻关闭手机。

如果在任何时刻电量降至 0 (变为 0 ),则无法在该时刻发送信息。

由于所有信息对斯捷潘都非常重要,他想知道是否可以在不给手机充电的情况下发送所有信息。

给出 需要发送的信息数量手机初始电量单位时间电量消耗 以及 依次关机和开机时的电量消耗
判断是否能够发送所有信息。
对于每组数据:
nfabm1m2m3mn

Solution

#define int long long//注意要开ll
int m[200010];
void solve()
{
    int n, f, a, b;
    cin >> n >> f >> a >> b;
    for (int i = 1; i <= n;i++)
        cin >> m[i];
    sort(m + 1, m + 1 + n);
    for (int i = 1; i <= n;i++)
    {
        if(a*(m[i]-m[i-1])>b)
            f -= b;
        else
            f -= a*(m[i]-m[i-1]);
    }
    if(f>0)//在这里f>=0?题目似乎没给清楚
        cout << "yes\n";
    else
        cout << "no\n";
}

D . Very Different Array

给出 a,b 数组,分别有 n,m(mn),在 b 数组中选出 n 个数组成一个长度为 n 的新数组使得:
D=i=1naici 最大并输出 max(D)

对于每组数据:

nma1a2anb1b2bm

Solution

我的想法是最大减去对应的最小的,但是是错误的

Hack 数据

2 6
7 9
8 1 10 6 3 9

按照我的思路:

expect 12 BUT found 11

一个正确的思路和我的很像却也不同:

因此做法是:

确定一个界限 i,先按照对应(大对应小)来计算 ans,后面只需要计算变化量即可。

可以枚举每一种情况

int a[200010], b[200010];
void solve()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= m; i++)
        cin >> b[i];

    sort(a + 1, a + n + 1);
    sort(b + 1, b + m + 1, greater<int>());

    long long ans = 0, tmp = 0;
    for (int i = 1; i <= n; i++)
        tmp += abs(a[i] - b[i]);
    ans = tmp;

    for (int i = 0; i < n; i++)
        tmp += abs(a[n - i] - b[m - i]) - abs(a[n - i] - b[n - i]),ans = max(ans, tmp);

    cout << ans << '\n';
}

E. Eat the Chip

示例1

Alice(白) 和 Bob(黑)能走的方向如图。双方都以最佳状态下棋,结果是?

对于每个样例:

hwxaxbyayb

Solution

如果有一方发现自己会输,就会想办法平局,分类讨论,较为麻烦

先算出两人见面之前 y 的范围,进攻方 [l1,r1],防守方 [l2,r2],满足:l1l2+1,r1r21,满足则可以 win,否则 Draw

void solve()
{
    int xs, ys, xa, ya, xb, yb;
    cin >> xs >> ys >> xa >> ya >> xb >> yb;
    if (xa >= xb)
    {
        cout << "Draw\n";
        return;
    }
    int x = xb - xa; //可达范围
    if (x % 2)
    {
        int la = max(1, ya - x / 2), ra = min(ys, ya + x / 2);
        int lb = max(1, yb - x / 2), rb = min(ys, yb + x / 2);
        if (la <= lb + 1 && ra >= rb - 1)
            cout << "Alice\n";
        else
            cout << "Draw\n";
    }
    else
    {
        int la = max(1, ya - x / 2), ra = min(ys, ya + x / 2);
        int lb = max(1, yb - (x - 1) / 2), rb = min(ys, yb + (x - 1) / 2);
        if (lb <= la + 1 && rb >= ra - 1)
            cout << "Bob\n";
        else
            cout << "Draw\n";
    }
}

F. Sum of Progression

给你一个由 n 个数字组成的数组 a 。还有 q 个形式为 s,d,k 的查询。

对于每个查询 q ,求 as+as+d2++as+d(k1)k 即:

i=1kas+d(i1)×i

对于每个测试用例:nqa1a2ans1d1k1s2d2k2(q query)sqdqkq

Solution

根号分治
设置一个阈值: $$w=\sqrt{ n }$$

d>w,直接暴力做(因为这时的运算次数很少了)

dw,开数组算前缀和. (s,d分别代表i,j)

处理方式可能不止一种...

int n,q,a[100010];
ll f[100010][350],g[100010][350];//序号 步长d 
sync_with_stdio(false), cin.tie(nullptr);//必须关闭同步流,不然会超时
void solve()
{
    cin >> n >> q;
	int value = sqrt(n);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int d = 1; d <= value; d++){
        for (int i = 1; i <= n; i++){
            f[i][d] = ((i - d > 0) ? f[i - d][d] : 0ll) + 1ll * a[i] *(i / d); //((i - 1) / d + 1);灰色的另一种也可以
            g[i][d] = ((i - d > 0) ? g[i - d][d] : 0ll) + a[i];
        }
    }
    ll ans;
    while (q--){
        cin >> s >> d >> k;
        ans = 0;
        if (d > value){
            for (int i = 0; i < k; i++)
                ans += 1ll * a[s + i * d] * (i + 1);
        }
        else{
            ans = f[s + d * (k - 1)][d] - ((s - d > 0) ? f[s - d][d] : 0);
            ans -= (g[s + d * (k - 1)][d] - ((s - d > 0) ? g[s - d][d] : 0)) * (s / d - 1); //((s - 1) / d);
        }
        cout << ans << '\n';
    }
}

G. Mischievous Shooter

谢尔只带了一把幸运猎枪,他可以朝四个方向之一射击:右下、左下、左上或右上。射击时,霰弹枪会击中所选方向上的所有目标,这些目标的曼哈顿距离不会超过一个固定常数 k.
k=3

每个测试用例:

nmkstr(m1)str(m2)str(mn)
其中字符". "表示单元格为空,字符 "#"表示存在目标.

输出一个整数,该整数等于一次射击击中目标的最大可能数目。

输入样例

4
3 3 1
.#.
###
.#.

2 5 3
###..
...##

4 4 2
..##
###.
#..#
####

2 1 3
#
#

输出样例

3
4
5
2

Notes:

Solution

(待更...)