• 大佬的难题


    大意:

    给你 3 个长度为 N 的排列 {a i }, {b i }, {c i }, 求

    ∑[a x < a y ][b x < b y ][c x < c y ], N ≤ 10 5

    1≤x,y≤n

    题解:

    直接容斥,设Sx,y表示满足上述式子的数量 答案即为Sx,y==3

    容易发现Sx,y只能取2,3

    设Pa,b 为a,b两个数组满足[ax<ay] [bx<by]的数量

    然后显然Pa,b+Pb,c+Pa,c=3*Sx,y==3 + Sx,y==2

    2Sx,y=Pab+Pbc+Pac-N*(N-1)>>1

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 using namespace std;
     8 typedef long long ll;
     9 const int N=2e6;
    10 int n;
    11 int a[N],b[N],c[N];
    12 long long seed;
    13 long long Rand() {
    14 return seed = ((seed*19260817) ^ 233333) & ((1<<24)-1);
    15 }
    16 void gen(int *a) {
    17     for(int i = 1; i <= n; i++) a[i] = i;
    18     for(int i = 1; i <= n; i++) swap(a[i], a[Rand()%i + 1]);
    19 }
    20 struct node{
    21     int a,b;
    22     bool operator<(const node &p)const{return a<p.a;}
    23 }tmp[N];
    24 int Tree[N*4];
    25 void add(int sta){
    26     for(int i=sta;i<=n;i+=(i&(-i)))Tree[i]++;
    27 }
    28 int getsum(int sta){
    29     int sum=0;
    30     for(int i=sta;i>=1;i-=(i&(-i)))sum+=Tree[i];
    31     return sum;
    32 }
    33 ll solve(int *a,int *b){
    34     ll ans=0;
    35     for(int i=1;i<=n;i++)tmp[i]=(node){a[i],b[i]};
    36     sort(tmp+1,tmp+n+1);
    37     for(int i=1;i<=n;i++){
    38         ans+=getsum(tmp[i].b);
    39         add(tmp[i].b+1);
    40     }
    41     memset(Tree,0,sizeof(Tree));
    42     return ans;
    43 }
    44 int main()
    45 {
    46     freopen("dalao.in","r",stdin);
    47     freopen("dalao.out","w",stdout);
    48     scanf("%d",&n);
    49     scanf("%lld",&seed);gen(a);
    50     scanf("%lld",&seed);gen(b);
    51     scanf("%lld",&seed);gen(c);
    52     ll t1=(ll)n*(n-1)>>1;
    53     ll t2=solve(a,b)+solve(a,c)+solve(b,c);
    54     printf("%lld
    ",(t2-t1)>>1);
    55     return 0;
    56 }

    另外就是60的CDQ 很好想:

    以a先排个序,然后就是b,c的二维选点,CDQ nlog2n玩过

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 using namespace std;
     8 typedef long long ll;
     9 const int N=500005;
    10 ll seed,ans=0;int a[N],b[N],c[N],n;
    11 ll Rand(){
    12     return seed=((seed*19260817)^233333)&((1<<24)-1);
    13 }
    14 void gen(int *a) {
    15     for(int i=1;i<=n;i++)a[i]=i;
    16     for(int i=1;i<=n;i++)swap(a[i],a[Rand()%i+1]);
    17 }
    18 struct node{
    19     int a,b,c;
    20 }q[N];
    21 bool comp(const node &p,const node &pp){return p.a<pp.a;}
    22 int Tree[N<<1];
    23 void add(int sta,int ad){
    24     for(int i=sta;i<=n;i+=(i&(-i)))Tree[i]+=ad;
    25 }
    26 int getsum(int sta){
    27     int sum=0;
    28     for(int i=sta;i>=1;i-=(i&(-i)))sum+=Tree[i];
    29     return sum;
    30 }
    31 bool check(node px,node qx){
    32     if(px.b!=qx.b)return px.b<=qx.b;
    33     return px.c<=qx.c;
    34 }
    35 node tmp[N];
    36 void cdq(int l,int r){
    37     if(l>=r)return ;
    38     int mid=(l+r)>>1;
    39     int xl=l,xr=mid+1,m=0;
    40     cdq(l,mid),cdq(mid+1,r);
    41     while(xl<=mid && xr<=r){
    42         if(check(q[xl],q[xr])){
    43             add(q[xl].c,1);
    44             tmp[++m]=q[xl++];
    45         }
    46         else{
    47             ans+=getsum(q[xr].c);
    48             tmp[++m]=q[xr++];
    49         }
    50     }
    51     while(xl<=mid){
    52         add(q[xl].c,1);
    53         tmp[++m]=q[xl++];
    54     }
    55     while(xr<=r){
    56         ans+=getsum(q[xr].c);
    57         tmp[++m]=q[xr++];
    58     }
    59     for(int i=1;i<=m;i++){
    60         if(tmp[i].a<=mid)add(tmp[i].c,-1);
    61         q[l+i-1]=tmp[i];
    62     }
    63 }
    64 void luang()
    65     {
    66         for(int i=1;i<=n;i++){
    67             q[i].a=a[i];q[i].b=b[i];q[i].c=c[i];
    68         }
    69         sort(q+1,q+n+1,comp);
    70         cdq(1,n);
    71         printf("%lld
    ",ans);
    72     }
    73 void work()
    74 {
    75     scanf("%d",&n);
    76     scanf("%lld",&seed);gen(a);
    77     scanf("%lld",&seed);gen(b);
    78     scanf("%lld",&seed);gen(c);
    79     if(n<=N)luang();
    80 }
    81 
    82 int main()
    83 {
    84     freopen("dalao.in","r",stdin);
    85     freopen("dalao.out","w",stdout);
    86     work();
    87     return 0;
    88 }
  • 相关阅读:
    go多种uuid生成方式
    go访问mysql基本语法
    go实现分布式唯一ID-snowflake(雪花算法)
    指定时间生成cron表达式
    zookeeper注册与发现
    短地址服务(二)
    java-redis
    短地址服务(一)
    cron表达式详解
    以后本blog所有内容全部转移,并在自建blog更新
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7142021.html
Copyright © 2020-2023  润新知