zoukankan      html  css  js  c++  java
  • 洛谷 P5677 [GZOI2017]配对统计(树状数组)

    传送门


    解题思路

    注意有个条件为ai互不相同。

    尝试应用lxl教的套路:
    第一步,将一维问题放到二维平面上:把好的配对(x,y)看做二维平面上的点。于是问题就变成了求出矩形所包含的点的个数。
    第二步,利用数据结构将二维平面问题降到一维解决:离线,把询问按照右端点排序,同时把好的配对按照右端点排序,保证在树状数组里的好的配对的x和y都小于等于当前的r。这样每次查询等于在树状数组里查询(l,r)的和。

    注意事项与细节:

    • 特判n==0的情况
    • 对于点(x,y)要保证x<=y

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn=3e5+5;
    int n,m,cnt,now;
    long long ans,d[maxn];
    struct node{
    	int l,r,id;
    	long long v;
    }a[maxn],b[maxn],q[maxn];
    bool cmp(node a,node b){
    	return a.r<b.r;
    }
    bool cmp2(node a,node b){
    	return a.v<b.v;
    }
    inline int lowbit(int x){
    	return x&(-x);
    }
    void update(int x,int v){
    	for(int i=x;i<=n;i+=lowbit(i)){
    		d[i]+=v;
    	}
    }
    long long query(int x){
    	long long res=0;
    	for(int i=x;i>=1;i-=lowbit(i)){
    		res+=d[i];
    	}
    	return res;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	cin>>n>>m;
    	if(n==1){
    		cout<<0;
    		return 0;
    	}
    	for(int i=1;i<=n;i++) cin>>a[i].v,a[i].id=i;
    	sort(a+1,a+n+1,cmp2);
    	a[0].v=-1e9;
    	a[n+1].v=2e9;
    	for(int i=1;i<=n;i++){
    		if(a[i].v-a[i-1].v<a[i+1].v-a[i].v){
    			b[++cnt].l=min(a[i-1].id,a[i].id);
    			b[cnt].r=max(a[i-1].id,a[i].id);
    		}else{
    			if(a[i].v-a[i-1].v==a[i+1].v-a[i].v){
    				b[++cnt].l=min(a[i-1].id,a[i].id);
    				b[cnt].r=max(a[i-1].id,a[i].id);
    				b[++cnt].l=min(a[i].id,a[i+1].id);
    				b[cnt].r=max(a[i].id,a[i+1].id);
    			}else{
    				b[++cnt].l=min(a[i].id,a[i+1].id);
    				b[cnt].r=max(a[i].id,a[i+1].id);
    			}
    		}
    	}
    	sort(b+1,b+cnt+1,cmp);
    	for(int i=1;i<=m;i++){
    		cin>>q[i].l>>q[i].r;
    		q[i].id=i;
    	}
    	sort(q+1,q+m+1,cmp);
    	for(int i=1;i<=m;i++){
    		while(now<cnt&&b[now+1].r<=q[i].r){
    			now++;
    			update(b[now].l,1);
    		}
    		ans+=1ll*q[i].id*(query(q[i].r)-query(q[i].l-1));
    		while(i<m&&q[i+1].r==q[i].r){
    			i++;
    			ans+=1ll*q[i].id*(query(q[i].r)-query(q[i].l-1));
    		}
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    11.28 正则表达式
    12.28jQuery 的取值赋值
    11.27 上传下载 图片预览
    11.28 验证控件
    12.23,repeater 分页显示
    12.23,搜索标记
    1.基础CRUD
    C#杀进程与之之子进程
    使用procedump捕获未处理异常的dump
    [.net core] 12.环境变量
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15273100.html
Copyright © 2011-2022 走看看