zoukankan      html  css  js  c++  java
  • 【Luogu】P2154虔诚的墓主人(树状数组)

      题目链接

      这题就是考虑我们有这样一个情况

      然后我们试图很方便地求出第三行第二个和第三个常青树之间所有点上下常青树的组合。

      考虑使用树状数组,一开始把数组平放在最底下,然后往上推。

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #define maxn 200020
    #define maxd 12
    #define mod 2147483648
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Tree{
        long long x,y;
        bool operator <(const Tree a)const{
            if(x!=a.x)    return x<a.x;
            return y<a.y;
        }
    }q[maxn];
    
    long long s[maxn*2],cnt;
    long long c[maxn][maxd];
    
    long long tree[maxn*2];
    inline long long low(long long x){    return x&(-x);    }
    
    inline void add(long long pos,long long lim,long long num){
        while(pos<=lim){
            tree[pos]+=num;
            tree[pos]%=mod;
            pos+=low(pos);
        }
        return;
    }
    
    inline long long query(long long pos){
        long long ans=0;
        while(pos){
            ans+=tree[pos];
            ans%=mod;
            pos-=low(pos);
        }
        return ans;
    }
    
    
    long long up[maxn],down[maxn];
    long long lef[maxn],rig[maxn];
    
    int main(){
        long long m=read()+1,n=read()+1;
        long long e=read();
        for(long long i=1;i<=e;++i){
            q[i]=(Tree){read(),read()};
            swap(q[i].x,q[i].y);
            s[++cnt]=q[i].x;    s[++cnt]=q[i].y;
        }
        sort(s+1,s+cnt+1);
        long long size=unique(s+1,s+cnt+1)-s-1;
        for(long long i=1;i<=e;++i){
            q[i].x=lower_bound(s+1,s+size+1,q[i].x)-s;
            q[i].y=lower_bound(s+1,s+size+1,q[i].y)-s;
        }
        sort(q+1,q+e+1);
        for(long long i=1;i<=e;++i){
            up[q[i].y]++;
            rig[q[i].x]++;
        }
        long long d=read();
        for(long long i=0;i<=e;++i)    c[i][0]=1;
        for(long long i=1;i<=e;++i)
            for(long long j=1;j<=d;++j)    c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
        long long ans=0;
        for(long long i=1;i<=e;++i){
            if(q[i].x==q[i-1].x&&i!=1){
                //printf("i=%d
    xi=%d yi=%d
    %d %d %d %d
    ",i,q[i].x,q[i].y,lef[q[i].x],rig[q[i].x],query(q[i].y),query(q[i].y-q[i-1].y));
                ans+=c[lef[q[i].x]][d]*c[rig[q[i].x]][d]*(query(q[i].y-1)-query(q[i-1].y))%mod;
            }
            
            up[q[i].y]--;    down[q[i].y]++;
            lef[q[i].x]++;    rig[q[i].x]--;
            add(q[i].y,size,c[up[q[i].y]][d]*c[down[q[i].y]][d]-query(q[i].y)+query(q[i].y-1));
        }
        printf("%lld
    ",(ans%mod+mod)%mod);
        return 0;
    }
  • 相关阅读:
    curl 抓取图片
    checkbox 全选
    大文件断点上传 js+php
    php快速排序
    直接插入排序(Straight Insertion Sort)
    选择排序 Selection sort
    57.猴子吃桃问题
    56.一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?
    55.输入两个正整数m和n,求其最大公约数和最小公倍数
    54.将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8952120.html
Copyright © 2011-2022 走看看