zoukankan      html  css  js  c++  java
  • BZOJ2441: [中山市选2011]小W的问题

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2441

    首先要注意到x1>x3且x5>x3(要是没有这个设定就是树状数组水题了。。

    这题正反做两个V乘起来就是答案了。。

    对y排序,每一个点找出在它左上方的点的个数记为sum,然后只要我们每次访问一个点的时候就把它对于在它右边的点的贡献全部删掉,那么询问一个点的答案就是在它左边所有点的sum之和了。

    具体写起来比较烦。。

    Orz http://blog.csdn.net/u012288458/article/details/48880559

    按id开线段树,每个点维护两个域分别表示相同点中最左那个点的id和第一个比它大的点的id

    首先这个算点的贡献,要这个点已经被计算过才可以减掉贡献,可以开一个变量来记录当前区间有多少个点已经被计算过。

    然后减贡献的时候,可以让这个点右边的所有的点都减掉贡献。然后加上贡献的时候只要也加上左边所有点点数就可以了。

    但是这样做的话要注意分开来做。毕竟贡献要全部减完才能来计算答案。。

    #include<cstring>
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define ll long long
    #define low(i) (i&(-i))
    #define maxn 200500
    #define mm 1000000007
    #define inf 2000000000
    using namespace std;
    struct node{int l,r,len; ll tag,sum;
    }t[maxn*4];
    struct data{int x,x2,y,id;
    }a[maxn]; 
    ll c[maxn],f[maxn][2];
    int n,tot,b[maxn];
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)){if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    bool cmp(data a,data b){
        return a.x<b.x;
    }
    bool cmp2(data a,data b){
        return a.y<b.y;
    }
    void up(int i){
        if (t[i].l==t[i].r) return;
        t[i].sum=0;
        t[i].len=t[i*2].len+t[i*2+1].len;
        if (t[i*2].len) t[i].sum=(t[i].sum+t[i*2].sum)%mm;
        if (t[i*2+1].len) t[i].sum=(t[i].sum+t[i*2+1].sum)%mm;
    }
    void push(int i,ll val){
        t[i].tag=(t[i].tag+val)%mm;
        t[i].sum=(t[i].sum+1LL*val*t[i].len)%mm;
    }
    void Down(int i){
        if (t[i].l==t[i].r) return;
        if (t[i].tag){
            push(i*2,t[i].tag); push(i*2+1,t[i].tag); 
            t[i].tag=0;
        } 
    }
    ll query(int i,int L,int R){
        if (L>R) return 0;
        if (t[i].len==0) return 0;
        int l=t[i].l,r=t[i].r,mid=(l+r)/2;
        Down(i);
        if (L<=l&&r<=R) return t[i].sum;
        if (R<=mid) return query(i*2,L,R);
        else if (L>mid) return query(i*2+1,L,R);
        else return (query(i*2,L,mid)+query(i*2+1,mid+1,R))%mm;
    }
    void change(int i,int pos,ll val){
        Down(i);
        if (t[i].l==t[i].r) {t[i].len=1; t[i].sum=(t[i].tag+val)%mm; return;}
        int mid=(t[i].l+t[i].r)/2;
        if (pos<=mid) change(i*2,pos,val);
        else change(i*2+1,pos,val);
        up(i);
    }
    void change2(int i,int L,int R,ll val){
        if (L>R) return;
        Down(i);
        int l=t[i].l,r=t[i].r,mid=(l+r)/2;
        if (L<=l&&r<=R){
            push(i,val); return;
        }
        if (R<=mid) change2(i*2,L,R,val);
        else if (L>mid) change2(i*2+1,L,R,val);
        else change2(i*2,L,mid,val),change2(i*2+1,mid+1,R,val);
        up(i);
    }
    void build(int i,int l,int r){
        t[i].l=l; t[i].r=r; 
        t[i].sum=t[i].tag=t[i].len=0;
        if (l==r) return;
        int mid=(l+r)/2;
        build(i*2,l,mid); build(i*2+1,mid+1,r);
    }
    
    void solve(){
        build(1,1,n);
        sort(a+1,a+1+n,cmp2);
        rep(i,1,n){
            int j=i;
            while (j<n&&a[i].y==a[j+1].y) j++;
            rep(k,i,j) change2(1,a[k].x2,n,-1);
            rep(k,i,j) f[a[k].id][0]=query(1,1,a[k].x-1);
            rep(k,i,j) change(1,a[k].id,a[k].x-1);
            i=j;    
         }
    }
    void solve2(){
        build(1,1,n);
        sort(a+1,a+1+n,cmp2);
        rep(i,1,n){
            int j=i;
            while (j<n&&a[i].y==a[j+1].y) j++;
            rep(k,i,j) change2(1,1,a[k].x-1,-1);
            rep(k,i,j) f[a[k].id][1]=query(1,a[k].x2,n);
            rep(k,i,j) change(1,a[k].id,n-a[k].x2+1);
            i=j;
        }
    }
    
    int main(){
        n=read();
        rep(i,1,n){
            a[i].x=read(); a[i].y=read(); 
            b[++tot]=a[i].x;
        }
        b[++tot]=inf;
        sort(b+1,b+1+tot);
        sort(a+1,a+1+n,cmp);
        rep(i,1,n) a[i].x2=upper_bound(b+1,b+1+tot,a[i].x)-b,a[i].x=lower_bound(b+1,b+1+tot,a[i].x)-b,a[i].id=i;
        solve();
        solve2();
        ll ans=0;
        rep(i,1,n) ans=(ans+f[i][0]*f[i][1]%mm)%mm;
        printf("%lld
    ",ans);
        return 0; 
    }
  • 相关阅读:
    公司上线流程 pushonline_alpha
    关于统计数据
    实习生新手指南1
    菜鸟代码学习散点总结(四)
    菜鸟机器学习散点总结(三)
    菜鸟机器学习散点总结(二)
    springboot 中事件监听模型的一种实现
    java 代码获取视频时长
    spring cloud 服务链路追踪 skywalking 6.1
    windows 中如何定位恶意软件的藏身位置
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5211378.html
Copyright © 2011-2022 走看看