• Luogu P3157 [CQOI2011]动态逆序对


    CDQ分治

    首先可以将答案分为之前有的逆序对数量+此操作产生的逆序对数量

    那么最后前缀和即可

    由于题目直接给出的是删除操作,并且加上初始序列的插入操作

    有两种不同会对答案造成影响的操作,不容易处理

    那么考虑从后往前考虑,那么删除操作就变成插入操作

    先将所有要删的数删完剩下的数,把它们作为初始序列

    然后进行CQD分治

    产生逆序对要求是

    $time_{i}<time_{j},val_{i}<val_{j},pos_{i}>pos_{j}$

    或$time_{i}<time_{j},val_{i}>val_{j},pos_{i}<pos_{j}$

    三维偏序问题

    在CDQ分治过程中,正的扫一遍,倒着扫一遍即可

      1 #include <bits/stdc++.h>
      2 #define int long long
      3 using namespace std;
      4 const int N=1e5+100;
      5 int n,m,a[N],b[N],ans[N];
      6 int p[N],w,dfn,tree[N],ti[N];
      7 struct node
      8 {
      9     int ti,pos,val,id;
     10 }sh[N];
     11 node t[N];
     12 int lowbit(int x)
     13 {
     14     return x&(-x);
     15 }
     16 void change(int x,int v)
     17 {
     18     while (x<=n)
     19     {
     20         if (ti[x]!=dfn)
     21         {
     22             ti[x]=dfn;
     23             tree[x]=0;
     24         }
     25         tree[x]+=v;
     26         x+=lowbit(x);
     27     }
     28 }
     29 int query(int x)
     30 {
     31     int ans=0;
     32     while (x>0)
     33     {
     34         if (ti[x]==dfn) ans+=tree[x];
     35         x-=lowbit(x);
     36     }
     37     return ans;
     38 }
     39 int ask(int l,int r)
     40 {
     41     return query(r)-query(l-1);
     42 }
     43 void cdq(int l,int r)
     44 {
     45     if (l==r) return;
     46     int mid=(l+r)>>1;
     47     cdq(l,mid);
     48     cdq(mid+1,r);
     49     dfn++;
     50     int tl=l,tr=mid+1;
     51     for (int i=l;i<=r;i++)
     52     {
     53         if ((tl<=mid && sh[tl].pos<sh[tr].pos) || tr>r)
     54         {
     55             change(sh[tl].val,1);
     56             tl++;
     57         }
     58         else
     59         {
     60             ans[sh[tr].id]+=ask(sh[tr].val+1,n);
     61             tr++;
     62         }
     63     }
     64     dfn++;//注意要将树状数组清零
     65     tl=mid;tr=r;//倒着统计
     66     for (int i=l;i<=r;i++)
     67     {
     68         if ((tl>=l && sh[tl].pos>sh[tr].pos) || tr<=mid)
     69         {
     70             change(sh[tl].val,1);
     71             tl--;
     72         }
     73         else
     74         {
     75             ans[sh[tr].id]+=ask(1,sh[tr].val-1);
     76             tr--;
     77         }
     78     }
     79     tl=l;tr=mid+1;
     80     for (int i=l;i<=r;i++)
     81     {
     82         if ((tl<=mid && sh[tl].pos<sh[tr].pos) || tr>r) t[i]=sh[tl++];
     83         else t[i]=sh[tr++];
     84     }//以pos为第二维从小到大归并排序
     85     for (int i=l;i<=r;i++) sh[i]=t[i];
     86 }
     87 signed main()
     88 {
     89     scanf("%lld%lld",&n,&m);
     90     for (int i=1;i<=n;i++)
     91       scanf("%lld",&a[i]);
     92     for (int i=1;i<=m;i++)
     93       scanf("%lld",&b[i]);
     94     for (int i=1;i<=m;i++) p[b[i]]=1;
     95     for (int i=1;i<=n;i++)
     96     {
     97         if (p[a[i]]==0)
     98         {
     99             w++;
    100             sh[w].ti=w;
    101             sh[w].val=a[i];
    102             sh[w].pos=i;
    103             sh[w].id=0;//原序列统计在一起,作为初始值
    104         }
    105         else p[a[i]]=i;
    106     }
    107     for (int i=m;i>=1;i--)//进行操作
    108     {
    109         w++;
    110         sh[w].ti=w;
    111         sh[w].val=b[i];
    112         sh[w].pos=p[b[i]];
    113         sh[w].id=m-i+1;
    114     }
    115     cdq(1,w);
    116     for (int i=1;i<=m;i++) ans[i]+=ans[i-1];
    117     for (int i=m;i>=1;i--)
    118       printf("%lld
    ",ans[i]);
    119 }
    View Code
  • 相关阅读:
    echarts属性杂记
    vue工作问题小计
    vue 表单数据修改,导致页面列表数据被同步修改问题的解决。
    利用syslog记录日志的简单日志函数
    1 概述
    PowerDesigner 如何自定义Data Type
    Mybatisplus读取(GeoJson)和保存Postgis geography数据
    【Mybatis】model类通过注解忽略某属性
    如何利用PostGIS正确计算距离和面积
    Linux上编写监控jar包重启脚本
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/12248453.html
Copyright © 2020-2023  润新知