zoukankan      html  css  js  c++  java
  • Guess the weight 题解(思维+线段树)

    题目链接

    题目大意

    这个题目也太难了把。。

    不看代码写,我感觉基本写不出

    还有要注意mid需要有时候移位

    官方题解有点小问题 分母应该是(n(n-1))

    还有一段大佬的话,看起来更好理解

    当前一共有 all 个卡牌,分母显然是 all * (all - 1) (就我们只需要考虑排列的前两个数,后面的不影响)然后,对于卡牌 i ,设 <i 的卡牌有 a 张, >i 的卡牌有 b 张,那么卡牌 i 一定挑 a,b 中大的那个方向选,所以可以发现存在一个分界线 x ,使得 <=x 的卡牌按大于它的策略,>x的卡牌按小于它的策略计算分子的话,就考虑卡牌对 (i,j) 对答案的贡献,如果它属于横跨分界线的,则先 i 后 j 和先 j 后 i 都是可行的;如果 (i,j) 在同一块里(即要么 i,j 都 <= x 要么 i,j 都 >x),那么它们先 i 后 j 和 先 j 后 i 中恰好有一个能产生贡献。所以我代码里那个就是 all * (all - 1) / 2 ,这个计算的就是假设 (i,j) 只有一个产生贡献,然后 all * (all - num) 就是跨越块新增的贡献,再减去 ban (指的就是 (i,i) 这种情形多算了,要被减掉)

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug printf(" I am here
    ");
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll> pii;
    mt19937 rnd(time(0));
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int maxn=2e5+5,inf=0x3f3f3f3f,mod=20071027;
    const double eps=1e-10;
    int n,q;
    ll sz;
    ll a[maxn];
    ll tree1[maxn<<2],tree2[maxn<<2];
    void push(int node){
        tree1[node]=tree1[node<<1]+tree1[node<<1|1]+tree2[node<<1]*tree2[node<<1|1];
        tree2[node]=tree2[node<<1]+tree2[node<<1|1];
    }
    void build(int node,int l,int r){
        if(l==r){
            tree1[node]=a[l]*a[l];
            tree2[node]=a[l];
            return ;
        }
        int mid=(l+r)/2;
        build(node<<1,l,mid);
        build(node<<1|1,mid+1,r);
        push(node);
    }
    void update(int node,int l,int r,int pos,int add){
        if(l==r){
            tree2[node]+=add;
            tree1[node]=tree2[node]*tree2[node];
            return ;
        }
        int mid=(l+r)/2;
        if(mid>=pos) update(node<<1,l,mid,pos,add);
        else  update(node<<1|1,mid+1,r,pos,add);
        push(node);
    }
    pii query_ans(int node,int L,int R,int l,int r){
        if(L>r||R<l){
            return {0,0};
        }
        if(L<=l&&r<=R){
            return {tree1[node],tree2[node]};
        }
        int mid=(l+r)/2;
        pii sum={0,0},temp1={0,0},temp2={0,0};
        if(mid>=L) temp1=query_ans(node<<1,L,R,l,mid);
        if(mid<R)  temp2=query_ans(node<<1|1,L,R,mid+1,r);
        sum={temp1.fi+temp2.fi+temp1.se*temp2.se,temp1.se+temp2.se};
        return sum;
    }
    int query_mid(int node,int l,int r,int sz){// 线段树上二分找分界点
        if(l==r){
            return l;
        }
        int mid=(l+r)/2,ans=-1;
        if(tree2[node<<1]>=sz) ans=query_mid(node<<1,l,mid,sz);
        else ans=query_mid(node<<1|1,mid+1,r,sz-tree2[node<<1]);
        return ans;
    }
    signed main(){
        int _;scanf("%d",&_);
        while(_--){
            for(int i=1;i<=200000;i++){
                a[i]=0;
            }
            scanf("%d%d",&n,&q);
            for(int i=1,x;i<=n;i++){
                scanf("%d",&x);
                a[x]++;
            }
            sz=n;
            build(1,1,200000);
            for(int i=1,opt,pos,add;i<=q;i++){
                scanf("%d",&opt);
                if(opt==1){
                    scanf("%d%d",&add,&pos);
                    sz+=add;
                    update(1,1,200000,pos,add);
                }else{
                    int mid=query_mid(1,1,200000,sz/2);
                    ll sum=query_ans(1,1,mid,1,200000).se,val=query_ans(1,mid,mid,1,200000).se;
                    if(sum-val>=sz-sum) mid--;
                    pii a=query_ans(1,1,mid,1,200000);
                    pii b=query_ans(1,mid+1,200000,1,200000);
                    // 去重自己不能选择自己
                    a.fi-=a.se;
                    b.fi-=b.se;
    
                    ll mu=sz*(sz-1);
                    ll zi=mu-a.fi-b.fi;
                    ll g=__gcd(mu,zi);
                    printf("%lld/%lld
    ",zi/g,mu/g);
                }
            }
        }
        return 0;
    }
    
    卷也卷不过,躺又躺不平
  • 相关阅读:
    Redis 安全
    Redis 数据备份与恢复
    Redis 服务器
    Redis 连接
    Redis 脚本
    Linux中使用netstat命令的基本操作,排查端口号的占用情况
    ElasticSearch 常用查询语句
    GO代码风格指南 Uber Go (转载)
    coding 注意事项(总结中)
    Byte字节
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15160658.html
Copyright © 2011-2022 走看看