• 2018 Multi-University Training Contest 2 杭电多校第二场


    开始逐渐习惯被多校虐orz  菜是原罪

    1004  Game    (hdoj 6312)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6312

    虽然披着博弈的外壳 但是也算是结论题 一开始开题的时候一看到博弈就不想写了 但是大佬们过题太快了 所以想到可能是结论题

    题意:有A和B两个人可以对一个1-n的全排列进行操作 每一次都可以删去一个数和它所有质子 A和B轮流进行操作 先删光全排列为赢 A先手 给出n 判断A的输赢

    因为每一次删数操作都会删去1 所以可以忽视掉1 直接看2-n的状态 如果在这个状态下B赢了 那么A先去选择1来转变自己的局面 A可以赢 如果2-n的状态下A赢了 可以不用专门去选择1 保持赢的状态 所以A是必胜的 

    知道这个结论后 代码就无比的简单了 不过要注意多组输入 这一场都要注意这个问题

    代码如下

     

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int main(){
        int n;
        while(scanf("%d",&n)!=EOF){
            printf("Yes
    ");
        }
        return 0;
    } 
    View Code

     

    1007  Naive Operations     (hdoj 6315)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6315

    需要优化的线段树

    题意:给一个全排列的数组b和为空的数组a 分为两个操作 第一个操作为给指定区间l-r a[l]-a[r]都加上1 第二个操作为给定指定区间 求b[l]/a[i]到b[r]/a[r]的和

    区间求和问题 一开始想到的是裸的树状数组 但是太暴力 华丽丽的给卡掉了 一直卡到了比赛结束

    每次对a数组进行++操作 都转化成--操作 具体做法为设一个minn赋值为对应的b[i]的值 一旦a[i]++,可以转换为minn--,直到minn为零 此时用于计数的sum进行++,minn重新赋值为b[i]

    代码如下

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    struct node{
        ll sum,pos,minn,lazy;
    }kk[maxn<<2];
    int a[maxn];
    void pushup(int rt){
        kk[rt].minn=min(kk[rt<<1].minn,kk[rt<<1|1].minn);
        kk[rt].sum=kk[rt<<1].sum+kk[rt<<1|1].sum;
    }
    void pushdown(int rt){
        if(kk[rt].lazy){
            kk[rt<<1].lazy+=kk[rt].lazy;
            kk[rt<<1|1].lazy+=kk[rt].lazy;
            kk[rt<<1].minn-=kk[rt].lazy;
            kk[rt<<1|1].minn-=kk[rt].lazy;
            kk[rt].lazy=0;
        }
    }
    void build(int l,int r,int rt){
        kk[rt].lazy=kk[rt].sum=0;
        if(l==r){
            kk[rt].minn=kk[rt].pos=a[l];
            kk[rt].sum=0;
            return ;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        pushup(rt);
    }
    void update(int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R&&kk[rt].minn>1){
            kk[rt].lazy++;
            kk[rt].minn--;
            return ;
        }
        if(l==r&&kk[rt].minn==1){
            kk[rt].sum++;
            kk[rt].minn=kk[rt].pos;
            kk[rt].lazy=0;
            return ;
        }
        int mid=(l+r)>>1;
        pushdown(rt);
        if(L<=mid) update(L,R,l,mid,rt<<1);
        if(R>mid) update(L,R,mid+1,r,rt<<1|1);
        pushup(rt);
    }
    ll query(int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R) return kk[rt].sum;
        int mid=(l+r)>>1;
        pushdown(rt);
        ll ans=0;
        if(L<=mid) ans+=query(L,R,l,mid,rt<<1);
        if(R>mid) ans+=query(L,R,mid+1,r,rt<<1|1);
        return ans;
    }
    int main(){
        int n,q,l,r;
        while(~scanf("%d%d",&n,&q)){
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            build(1,n,1);
            while(q--){
                char s[10];
                scanf("%s%d%d",s,&l,&r);
                if(s[0]=='a') update(l,r,1,n,1);
                if(s[0]=='q') printf("%lld
    ",query(l,r,1,n,1));
            }
        }
        return 0;
    }
    View Code

     

     

    1011  Swaps and Inversions     (hdoj 6318)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6318

    树状数组+离散化 求逆序数

    题意:给出一个数列 如果一个数的逆序数不为0 则要付出逆序数*x的代价 但是也可以选择交换相邻两项来减少逆序数 每次交换需要付出的代价为y

    只要想到这是逆序数 就是一题板子题了 因为相邻两项也可以构成逆序对 所以就可以把问题简化为逆序数和*min(x,y)

    逆序数在线性代数中有定义(orz还好没忘记这学期刚学的线代)一个数的逆序数 是在这个数之后所有比它要小的数字个数的和 这里可以用离散化的思想来处理 用树状数组来进行修改和查询

    有个小坑 一直wa 后知后觉发现是姿势不对orz 在排序的时候进行特判 差不多一个结构体二重排序(?)

    哦对了 会爆int 要开long long

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    typedef long long ll;
    int c[maxn],pos[maxn]; 
    int n;
    struct node{
        int v;
        int id;
    }kk[maxn];
    int cmp(node a,node b){
        if(a.v==b.v) return a.id<b.id;
        else return a.v<b.v;
    }
    int lowbit(int x){
        return x&(-x);
    }
    void insert(int i,int x){
        while(i<=n){
            c[i]+=x;
            i+=lowbit(i);
        }
    }
    ll getsum(int i){
        ll sum=0;
        while(i>=1){
            sum+=c[i];
            i-=lowbit(i);
        } 
        return sum;
    }
    int main(){
        int x,y;
        while(~scanf("%d%d%d",&n,&x,&y)){
            ll ans=0;
            for(int i=1;i<=n;i++){
                scanf("%d",&kk[i].v);
                kk[i].id=i;
            }
            sort(kk+1,kk+n+1,cmp);
            for(int i=1;i<=n;i++){
                pos[kk[i].id]=i;
            }
            memset(c,0,sizeof(c));
            for(int i=1;i<=n;i++){
                insert(pos[i],1);
                ans+=i-getsum(pos[i]);
            }
            printf("%lld
    ",(ll)ans*min(x,y));
        }
        return 0;
    }
    View Code

     

  • 相关阅读:
    IE6-IE11兼容性问题列表及解决办法
    EJB--事务管理 .
    JDBC批处理---(java 对数据库的回滚) .
    redisb并发访问慢出现的问题
    redis其他问题
    多线程实现服务器端接收连接
    序列化作用
    redis的key过期时间
    nginx负载均衡和反向代理有什么区别
    nginx的负载均衡和反响代理配置
  • 原文地址:https://www.cnblogs.com/whdsunny/p/9378711.html
Copyright © 2020-2023  润新知