zoukankan      html  css  js  c++  java
  • CF283E Cow Tennis Tournament

    线段树+组合数学

    这道题直接做好像根本不可做,考虑转化:我们可以用任意方案数-不合法的方案数,那么答案为:$$C_n^3 - sum_{i=1}^{n} C_{ki}^2$$
    其中ki为第i个点能打赢的人数。为什么是这样的:一个方案不合法只要一个人能打赢两个人就行了。

    怎么求ki?考虑线段树,首先将所有人的战斗力排序,然后求出每一个操作的左右端点,然后我们按照左端点排序。每次我们扫描到第i个人时就将左端点为i的操作全部实现(用线段树)然后查询[i+1,n]中被翻转了奇数次的,然后查询[1,i-1]中被翻转了偶数次的。如果i这个点是某项操作的右端点,那么操作完后要去掉她的影响(对后面没有影响了)

    收获:注意补集转化

    code:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<set>
    #include<map>
    #include<vector>
    #define maxn 200000
    #define SZJ int
    #define AK main
    #define half (l+r)>>1
    #define SDOI () 
    using namespace std;
    #define rep (i,a,b) for (int i=a;i<=b;++i) 
    #define erpe (i,a) for (int i=head[a];i!=-1;i=e[i].next)
    #define int long long
    struct hzw
    {
        int l,r; 
    }t[maxn]; 
    struct zmd
    {
        int lc,rc,tag,sum;
    }tre[maxn];
    int n,k,num[maxn];
    vector<int>bkt[100006];
    inline bool cmp(hzw a,hzw b)
    {
        if (a.l==b.l) return a.r<b.r;
        else return a.l<b.l;
    }
    inline void pushdown(int s,int l,int r)
    {
        int mid=half;
        int tmp=tre[s].tag%2;
        if (!tmp) {tre[s].tag=0;return;}
        int lson=tre[s].lc,rson=tre[s].rc;
        tre[lson].sum=(mid-l+1)-tre[lson].sum,tre[lson].tag+=tre[s].tag;
        tre[rson].sum=(r-mid)-tre[rson].sum,tre[rson].tag+=tre[s].tag;
        tre[s].tag=0;
    }
    int cnt=0;
    inline void build(int s,int l,int r)
    {
        if (l==r) return;
        int mid=half;
        tre[s].lc=++cnt;
        build(tre[s].lc,l,mid);
        tre[s].rc=++cnt;
        build(tre[s].rc,mid+1,r);
    }
    inline void update(int s,int l,int r,int cl,int cr)
    {
        if (l==cl&&r==cr)
        {
            tre[s].sum=(r-l+1)-tre[s].sum;
            tre[s].tag++;
            return;
        }
        if (tre[s].tag) pushdown(s,l,r);
        int mid = half;
        if (cr<=mid) update(tre[s].lc,l,mid,cl,cr);
        else if (cl>mid) update(tre[s].rc,mid+1,r,cl,cr);
        else 
        {
            update(tre[s].lc,l,mid,cl,mid);
            update(tre[s].rc,mid+1,r,mid+1,cr);	
        } 
        tre[s].sum=tre[tre[s].lc].sum+tre[tre[s].rc].sum;
    }
    inline int query(int s,int l,int r,int cl,int cr)
    {
        if (l==cl&&r==cr) return tre[s].sum;
        if (tre[s].tag) pushdown(s,l,r);
        int mid=half;
        if (cr<=mid) return query(tre[s].lc,l,mid,cl,cr);
        else if (cl>mid) return query(tre[s].rc,mid+1,r,cl,cr);
        else 
        {
            return query(tre[s].lc,l,mid,cl,mid)+query(tre[s].rc,mid+1,r,mid+1,cr);
        }
    }
    #undef int 
    SZJ AK SDOI
    {
    
        #define int long long 
        cnt=1;
        cin>>n>>k;
        for (int i=1;i<=n;++i) cin>>num[i];	
        sort(num+1,num+1+n);
        build(1,1,n);
        num[n+1]=1e17;
        int fina=n*(n-1)*(n-2)/6;
        for (int i=1,a,b;i<=k;++i)
        {
            cin>>a>>b;
            t[i].l=lower_bound(num+1,num+1+n,a)-num;
            t[i].r=upper_bound(num+1,num+1+n+1,b)-num-1;
            if (t[i].l>t[i].r) t[i].l=1e17,t[i].r=1e17;
        }
        sort(t+1,t+1+k,cmp);
        int now=1;
        for (int i=1;i<=n;++i)
        {
            while (t[now].l==i) update(1,1,n,t[now].l,t[now].r),bkt[t[now].r].push_back(t[now].l),now++;
            int tmp=0;
            if (i>1) tmp+=query(1,1,n,1,i-1);
            if (i<n) tmp+=(n-i)-query(1,1,n,i+1,n);
            for (int j=0;j<bkt[i].size();++j) update(1,1,n,bkt[i][j],i);
            fina-=tmp*(tmp-1)/2;
        }
        cout<<fina;
    } 
    
  • 相关阅读:
    node.js
    js中文乱码问题
    238. Product of Array Except Self
    接下来要记得东西
    javascript 块内函数
    171. Excel Sheet Column Number
    Moore’s Voting Algorithm
    [ Python ] PIL
    [ Python ] KMP Algorithms
    房之事
  • 原文地址:https://www.cnblogs.com/bullshit/p/9899535.html
Copyright © 2011-2022 走看看