• Jzoj5608 Subset


    这道题非常有意思

    首先我们可以发现,对于一个合法的三元组我们可以找到一个大小小于3的下标集合S与之对应

    那么我们就来考虑找到所有合法的这样的S

    当|S|=1时,显然都是成立的

    当|S|=2时,我们只需要保证s中两个元素i,j不满足a[i]<a[j],b[i]<b[j],c[i]<c[j]就可以了

    考虑计算不满足的方案,可以用cdq分治+fenwick完成

    当|S|=3时,我们直接计算比较困难,我们考虑两种不合法的情况

    1.存在一个元素x满足a[x],b[x],c[x]都是最大的

    2.存在一个元素x满足a[x],b[x],c[x]中有两个是最大的

    对于第一种情况,我们可以沿用计算|S|=2时的结果,乘上一个组合数,设这部分的答案为A

    对于第二种情况,我们可以考虑容斥,先设这部分的答案为B

    让后我们可以考虑计算对于一个元素x,a[x],b[x],c[x]存在至少两个是最大的

    直接枚举哪两个是最大的让后按照其中一个排序,另一个用fenwick维护

    那么设这样计算的答案为X,显然有X=A*3+B 那么我们就得到了B

    用总方案数减掉A和B就是|S|=3时的答案

    好题!

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int n,m,w[100010]; long long A,B,X,S=0;
    struct dt{ int a,b,c,G; } s[100010],b[100010];
    inline bool c1(dt a,dt b){ return a.a<b.a; } 
    inline bool c2(dt a,dt b){ return a.b<b.b; } 
    void cdq(int l,int r){
    	if(l==r) return;
    	int m=l+r>>1,i,j,t=l,a=s[m].a;
    	cdq(l,m); cdq(m+1,r);
    	for(i=l,j=m+1;i<=m && j<=r;)
    		if(s[i].b<s[j].b){
    			for(int x=s[i].c;x<=n;x+=x&-x) ++w[x];
    			b[t++]=s[i++];
    		} else {
    			for(int x=s[j].c;x;x&=x-1) s[j].G+=w[x];
    			b[t++]=s[j++];
    		}
    	for(;i<=m;){
    		for(int x=s[i].c;x<=n;x+=x&-x) ++w[x];
    		b[t++]=s[i++];
    	}
    	for(;j<=r;){
    		for(int x=s[j].c;x;x-=x&-x) s[j].G+=w[x];
    		b[t++]=s[j++];
    	}
    	for(;l<=r;++l){
    		s[l]=b[l];
    		if(s[l].a<=a) 
    		for(int x=s[l].c;x<=n;x+=x&-x) --w[x];
    	}
    }
    int main(){
    	freopen("subset.in","r",stdin);
    	freopen("subset.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d",&s[i].a);
    	for(int i=1;i<=n;++i) scanf("%d",&s[i].b);
    	for(int i=1;i<=n;++i) scanf("%d",&s[i].c);
    	sort(s+1,s+1+n,c1); cdq(1,n);
    	for(int i=1;i<=n;++i) A+=(s[i].G*(s[i].G-1ll)>>1);
    	sort(s+1,s+1+n,c1);
    	int w[100010]={0};
    	for(int i=1,j,t;i<=n;++i){
    		for(t=0,j=s[i].b;j;j&=j-1) t+=w[j];
    		for(j=s[i].b;j<=n;j+=j&-j) w[j]++;
    		X+=t*(t-1ll)>>1;
    	}
    	memset(w,0,sizeof w);
    	for(int i=1,j,t;i<=n;++i){
    		for(t=0,j=s[i].c;j;j&=j-1) t+=w[j];
    		for(j=s[i].c;j<=n;j+=j&-j) w[j]++;
    		X+=t*(t-1ll)>>1;
    	}
    	sort(s+1,s+1+n,c2);
    	memset(w,0,sizeof w);
    	for(int i=1,j,t;i<=n;++i){
    		for(t=0,j=s[i].c;j;j&=j-1) t+=w[j];
    		for(j=s[i].c;j<=n;j+=j&-j) w[j]++;
    		X+=t*(t-1ll)>>1;
    	}
    	B=X-A*3; S=n*(n+1ll)>>1;
    	for(int i=1;i<=n;++i) S-=s[i].G;
    	S+=n*(n-1ll)*(n-2ll)/6; S-=A+B;
    	printf("%lld
    ",S);
    }

  • 相关阅读:
    Study Plan The Twelfth Day
    Study Plan The Fifteenth Day
    Study Plan The Seventeenth Day
    Study Plan The Tenth Day
    Study Plan The Eighth Day
    Study Plan The Eleventh Day
    Study Plan The Sixteenth Day
    Study Plan The Thirteenth Day
    Study Plan The Fourteenth Day
    Study Plan The Ninth Day
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477110.html
Copyright © 2020-2023  润新知