2018 Multi-University Training Contest 2 - (1004,1010,1007)

                                                1004 Game

题意:两个人玩游戏,一开始有n个数1~n,两人轮流操作,每轮选择一个没有被拿走的数,然后拿走它和他所有约数。拿光所有数的人获胜,给定n问先手必胜还是后手必胜。

解析:图片来自多校交流群,侵删。

2018 Multi-University Training Contest 2 - (1004,1010,1007)_第1张图片

 

                               1010 Swaps and Inversions

题意:有长为n的序列,序列中每个逆序要交y元钱,但是可以通过花x元钱来交换两个相邻的元素。问最小花费。

解析:注意到逆序对数=交换相邻元素需要交换的次数,那么输出 min(x,y)*逆序对个数 即可。这里用树状数组+离散化来求逆序数。

代码:

#include
using namespace std;
int a[100105],n,x,y;
long long ans;
struct AA
{
    int x,num,now;
}pos[100105];//若数组开为100005会RE,很迷。
bool cmp(AA aa,AA bb)
{
    return aa.x0)
    {

        s+=a[i];
        i-=lowbit(i);
    }
    return s;
}
int main()
{
    while(~scanf("%d%d%d",&n,&x,&y))
    {
        memset(a,0,sizeof(a));
        ans=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&pos[i].num);
            pos[i].x=i;
        }
        sort(pos+1,pos+1+n,cmpp);
        int k=1;
        pos[1].now=1;
        for(int i=2;i<=n;i++)
        {
            if(pos[i].num==pos[i-1].num) pos[i].now=k;
            else pos[i].now=++k;
        }
        sort(pos+1,pos+1+n,cmp);
        for(int i=1;i<=n;i++)
        {
            add(pos[i].now);
            ans+=i-sum(pos[i].now);
        }
        cout<

 

                              1007 Naive Operations

题意:有a,b两个串,b数组给定初值后是固定的,a数组初值为0;现有q次操作,操作有两种①.add l r:对[al,ar]区间内元素全部加一;②.query l r:求∑ l...r (⌊ai/bi⌋)

解析:显然当ai的add次数大于等于bi次时,才会对结果有影响,那么q次操作不会带来太多次的答案影响。

①.用线段树维护i位置还差多少次add能对答案产生一次影响,即i位置初始为bi,每次add使其减一,减到0时i位置即对答案贡献1,此时使答案数组c的i位置加1,然后将此处再设置为bi。这里判断哪个位置减到0了就是用线段树维护区间最小值来查询位置。

②.答案数组c用树状数组维护,方便区间查询。

代码(ayf大佬的代码):

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mod 1000000007
#define PI acos(-1)
#define ll long long
#define inf 999999
#define ull unsigned long long
using namespace std;

#define MAXN 100010
#define inf 0x3f3f3f3f
struct node{
    int l,r;//区间[l,r]
    int add;//区间的延时标记
    int mn; //区间最小值
}tree[MAXN<<2];//一定要开到4倍多的空间

int b[MAXN<<2];

int c[MAXN],n;
int lowbit(int i) {return i&(-i);}
void update(int i,int val)
{
    while(i<=n)
    {
        c[i]+=val;
        i+=lowbit(i);
    }
}
int getsum(int i)
{
    int sum=0;
    while(i>0)
    {
        sum+=c[i];
        i-=lowbit(i);
    }
    return sum;
}
void pushup(int index)
{
    tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
}
void pushdown(int index)
{
    if(tree[index].add)
    {
        tree[index<<1].mn += tree[index].add;
        tree[index<<1|1].mn += tree[index].add;
        tree[index<<1].add += tree[index].add;
        tree[index<<1|1].add += tree[index].add;
        tree[index].add = 0;
    }
}
void build(int l,int r,int index)
{
    tree[index].l = l;
    tree[index].r = r;
    tree[index].add = 0;
    if(l == r)
    {
        scanf("%d",&b[index]);
        tree[index].mn=b[index];
        return ;
    }
    int mid = (l+r)>>1;
    build(l,mid,index<<1);
    build(mid+1,r,index<<1|1);
    pushup(index);
}
void solve(int index)//找0位置
{
    if(tree[index].l==tree[index].r)
    {
        if(tree[index].mn==0) tree[index].mn=b[index];
        update(tree[index].l,1);
        return ;
    }
    pushdown(index);
    int mid=(tree[index].l+tree[index].r)>>1;
    if(tree[index*2].mn==0) solve(index*2);
    if(tree[index*2+1].mn==0) solve(index*2+1);
    pushup(index);
}
void updata(int l,int r,int index,int val)
{
    if(l <= tree[index].l &&r>=tree[index].r)
    {
        tree[index].mn += val;
        tree[index].add += val;
        if(tree[index].mn==0)//区间[tree[index].l,tree[index].r]中出现0,对结果产生影响,需要修改c数组的值
        {
            solve(index);
        }
        return ;
    }
    pushdown(index);
    int mid = (tree[index].l+tree[index].r)>>1;
    if(l <= mid) updata(l,r,index<<1,val);
    if(r > mid) updata(l,r,index<<1|1,val);
    pushup(index);
}
int main()
{
    int q,l,r;
    char s[20];
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        memset(tree,0,sizeof(tree));
        build(1,n,1);
        while(q--)
        {
            scanf("%s%d%d",s,&l,&r);
            if(s[0]=='a')
            {
                updata(l,r,1,-1);
            }
            else
            {
                cout<

 

你可能感兴趣的:(ACM比赛练习)