zoukankan      html  css  js  c++  java
  • 四维偏序

    题意:

    给定(n)个元素,每个元素有四个属性(a,b,c,d),求序列中满足(a_i< a_j)(b_i< b_j)(c_i< c_j)(d_i< d_j)的数对((i,j))的个数。

    对于(100%)的数据,(1<=n<=50000),保证所有的(ai,bi,ci,di)分别组成四个(1)~(n)的排列。

    思路:

    第一维排序。
    第二维cdq分治,在保持第二维有序的情况下,记录第一维的顺序(即此元素是否可以更新其他元素或是否可以被更新)
    第三维继续cdq分治,维持第三维有序性
    第四维在以上的前提下,用树状数组维护统计答案

    注意事项:

    谨防手残

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=50005;
    int n,ans;
    struct node{int a,b,c,d,tp;}q[N],tmp1[N],tmp2[N];
    inline bool cmp1(node x,node y){return x.a<y.a;}
    inline int read()
    {
    	int s=0,w=1; char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    	for(;isdigit(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    	return s*w;
    }
    struct tree{
    	int cc[N];
    	inline int lowbit(int x){return x&(-x);}
    	inline void add(int x,int v)
    	{
    		for(;x<=n;x+=lowbit(x))cc[x]+=v;
    	}
    	inline int query(int x)
    	{
    		int anss=0;
    		for(;x;x-=lowbit(x))anss+=cc[x];
    		return anss;
    	}
    }T;
    void cdq3d(int l,int r)
    {
    	if(l==r) return;
    	int mid=l+r>>1;
    	cdq3d(l,mid);cdq3d(mid+1,r);
    	int i=l,j=mid+1,cnt2=l;
    	while(j<=r)
    	{
    		while(tmp1[i].c<tmp1[j].c&&i<=mid)
    		{
    			if(tmp1[i].tp==1) T.add(tmp1[i].d,1);
    			tmp2[cnt2++]=tmp1[i++];
    		}
    		if(tmp1[j].tp==2) ans+=T.query(tmp1[j].d);
    		tmp2[cnt2++]=tmp1[j++];
    	}
    	for(int e=l;e<i;++e)
    		if(tmp1[e].tp==1) T.add(tmp1[e].d,-1);
    	for(int e=i;e<=mid;++e) tmp2[cnt2++]=tmp1[e];
    	for(int e=l;e<=r;++e) tmp1[e]=tmp2[e];
    }
    void cdq2d(int l,int r)
    {
    	if(l==r) return;
    	int mid=l+r>>1;
    	cdq2d(l,mid);cdq2d(mid+1,r);
    	int i=l,j=mid+1,cnt1=l;
    	while(j<=r)
    	{
    		while(q[i].b<q[j].b&&i<=mid) q[i].tp=1,tmp1[cnt1++]=q[i++];
    		q[j].tp=2,tmp1[cnt1++]=q[j++];
    	}
    	for(int e=i;e<=mid;++e) q[e].tp=1,tmp1[cnt1++]=q[e];
    	for(int e=l;e<=r;++e) q[e]=tmp1[e];
    	cdq3d(l,r);
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)q[i].a=read();
    	for(int i=1;i<=n;++i)q[i].b=read();
    	for(int i=1;i<=n;++i)q[i].c=read();
    	for(int i=1;i<=n;++i)q[i].d=read();
    	sort(q+1,q+n+1,cmp1);
    	cdq2d(1,n);
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    Oracle入门第六天(下)——高级子查询
    Oracle入门第六天(中)——SET运算符(交并差集)
    Oracle入门第六天(上)——用户控制
    数据库理论——数据库3范式
    Oracle入门第五天(下)——数据库其他对象
    Oracle入门第五天(上)——数据库对象之视图
    PHP PDO函数库详解
    python访问纯真IP数据库的代码
    有关linux磁盘分区优化
    Nginx日志深入详解
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/12041304.html
Copyright © 2011-2022 走看看