2018 hdu 多校 2

这次的题有点难,慢慢补吧……

http://acm.hdu.edu.cn/search.php?field=problem&key=2018+Multi-University+Training+Contest+2&source=1&searchmode=source
1004
这道题就是一个比较典型的博弈,分析一下1怎么拿就行,最后答案就是先手必胜,Yes

1010

这道题的题意是给一个全排列,然后一个逆序对要花费x元,交换相邻的数一次要y元,然后问最小的花费。
因为一开始的逆序数是个常数,然后每次交换肯定会减少一个逆序对,那么只要求出 逆序数*min(x,y)

1007
题意就是维护一个数列,执行区间加一和查询的操作。
场上准备使用莫队算法乱搞,结果没写出来。
正解是使用线段树,维护一个最小值,初始值是B的值,当叶子节点的最小值变一的时候,给区间和加一,最后查询的时候查询和就行了。

为什么要这样做呢,首先查询的和是[ai/bi],ai的初始条件是0,每次加一的时候,要么会发生整除(1),也就是ai达到了bi的大小,要么是0,也就是ai没有达到bi的大小,每次发生整除的时候给sum加上一,然后把最小值重新赋值b的大小。
可以证明的是最后的时间复杂度是 O ( N l o g 2 N )

#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
using namespace std;
#define LL long long
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 111111;
LL add[maxn<<2];
LL sum[maxn<<2];
LL minv[maxn<<2];
LL b[maxn];
int n,m;
void PushUp(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    minv[rt] = min(minv[rt<<1],minv[rt<<1|1]);
}
void PushDown(int rt)
{
    if (add[rt])
    {
        add[rt<<1] += add[rt];
        add[rt<<1|1] += add[rt];
        minv[rt<<1] -= add[rt];
        minv[rt<<1|1] -= add[rt];
        add[rt] = 0;
    }
}
void build(int l,int r,int rt)
{
    add[rt] = 0;
    if (l == r)
    {
        minv[rt] = b[l];
        sum[rt] = 0;
        return;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUp(rt);
}
void update(int L,int R,int l,int r,int rt)
{
    if(minv[rt] > 1 && l ==L && r  ==R)
    {
        add[rt]++;
        minv[rt]--;
        return;
    }
    if(l == r && minv[rt] == 1)
    {
        sum[rt] += 1;
        add[rt] = 0;
        minv[rt] = b[l];
        return ;
    }
    PushDown(rt);
    int m = (l + r) >> 1;
    if(R <= m) update(L,R,lson);
    else if(L > m) update(L,R,rson);
    else update(L,m,lson),update(m+1,R,rson);
    PushUp(rt);
}
LL query(int L,int R,int l,int r,int rt)
{
    if (L <= l && r <= R)
    {
        return sum[rt];
    }
    if(minv[rt] <= 0) update(L,R,1,n,1);
    PushDown(rt);
    int m = (l + r) >> 1;
    LL ret = 0;
    if (L <= m)
        ret += query(L, R, lson);
    if (m < R)
        ret += query(L, R, rson);
    return ret;
}
int main()
{
    char op[10];
    while(scanf("%d%d",&n,&m) != EOF)
    {
        for(int i = 1; i<=n; i++)
        {
            scanf("%lld", &b[i]);
        }
        build(1,n,1);
        for(int i = 1; i<=m; i++)
        {
            int a,b;
            scanf("%s %d %d",op,&a,&b);
            if(op[0] == 'a')
            {
                update(a,b,1,n,1);
            }
            else
            {
                printf("%lld\n",query(a,b,1,n,1));
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lingzidong/article/details/81217653
今日推荐