• 【bzoj4889】: [Tjoi2017]不勤劳的图书管理员 分块-BIT


    【bzoj4889】: [Tjoi2017]不勤劳的图书管理员

    题目大意:给定一个序列(n<=50000),每个数有一个编码ai(ai<=50000)和权值vi(vi<=100000),每次交换两个数的位置,交换m次(m<=50000)

    求每次交换后的序列的杂乱度对1e9+7取模(对于每一对是逆序对的编码会产生两者权值和的杂乱度)。

    感觉正解是什么奇怪的树套树?蒟蒻只会分块水题。。

    先用BIT求一遍初始状态的杂乱度。。(不要问我为什么一开始是BIT。。因为打暴力正好用到就懒得改了。。感觉直接分块也行)

    然后开始分块。。分块完对每个块内排序,然后求出排序完之后的权值前缀和。

    考虑每次交换操作,若原有序列是 A B C D E,交换B D

    那么其实改变的杂乱度只跟B->D的序列有关,跟A E无关

    仔细讨论一下就是

    当aB<aD

    改变的杂乱度会是

    C段里所有编号比aB大的权值和 + C段里所有编号比aB大的个数*vB  -  C段里所有编号比aB小的权值和 - C段里所有编号比aB小的个数*vB

    C段里所有编号比aD小的权值和 + C段里所有编号比aD小的个数*vD  -  C段里所有编号比aD大的权值和 - C段里所有编号比aD大的个数*vD

    当aB>aD

    贡献符号相反。

    如果B!=D 还会加上 vB+vD的贡献

    按照这种讨论在分块里各种暴力瞎搞二分就好了。。

    然后最后再把BD所在的块暴力重建就做完了。。

      1 /* http://www.cnblogs.com/karl07/ */
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <algorithm>
      7 using namespace std;
      8 
      9 #define ll long long 
     10 #define lowbit(x) (x&-x)
     11 const int N=1e5+5;
     12 const int P=1e9+7;
     13 const int MX=1e5;
     14 int n,m,cnt;
     15 int pos[N],st[N];
     16 ll bit[N],bb[N];
     17 ll lst=0;
     18 struct data{
     19     int x,y;
     20 }a[N],b[N];
     21 
     22 bool oper(data a,data b){
     23     return a.x<b.x;
     24 }
     25 
     26 void modify(int i){
     27     for (int j=st[i];j<st[i+1];j++){
     28         b[j].x=a[j].x;
     29         b[j].y=a[j].y;
     30     }
     31     sort(b+st[i],b+st[i+1],oper);
     32     for (int j=st[i]+1;j<st[i+1];j++){
     33         b[j].y=(b[j].y+b[j-1].y)%P;
     34     }
     35 }
     36 
     37 int find(int l,int r,int x){
     38     int mid=(l+r)/2,ans=l-1;
     39     while (l<=r){
     40         mid=(l+r)/2;
     41         if (b[mid].x<x){
     42             ans=mid;
     43             l=mid+1;
     44         }else{
     45             r=mid-1;
     46         }
     47     }
     48     return ans;
     49 }
     50 
     51 ll query(int x,int mn,int mx,int ny,int xy){
     52     int p1=find(st[x],st[x+1]-1,mx),p2=find(st[x],st[x+1]-1,mn);
     53     ll ans=0;
     54     ans+=(b[p1].y)*(p1>=st[x])+(p1-st[x]+1)*xy%P;
     55     ans+=b[st[x+1]-1].y-b[p2].y*(p2>=st[x])+ny*(st[x+1]-1-p2)%P;
     56     swap(p1,p2);
     57     ans-=(b[p1].y)*(p1>=st[x])+(p1-st[x]+1)*ny%P;
     58     ans-=b[st[x+1]-1].y-b[p2].y*(p2>=st[x])+xy*(st[x+1]-1-p2)%P;
     59     return ans%P;
     60 }
     61 
     62 void build(){
     63     int sz=sqrt(n)/2;
     64     for (int i=1;i<=n;i++){
     65         if (sz==1 || i%sz==1){
     66             st[++cnt]=i;
     67         }
     68         pos[i]=cnt;
     69     }
     70     st[cnt+1]=n+1;
     71     for (int i=1;i<=cnt;i++){
     72         modify(i);
     73     }
     74 }
     75 
     76 void Modify(int x,int y){
     77     while (x<=MX){
     78         bit[x]+=y;
     79         bb[x]++;
     80         bit[x]%=P;
     81         x+=lowbit(x);
     82     }
     83 }
     84 
     85 ll Query(int x,int y){
     86     ll ans=0,a2=0;
     87     while (x){
     88         ans+=bit[x];
     89         a2+=bb[x];
     90         ans%=P;
     91         x-=lowbit(x);
     92     }
     93     ans+=a2*y%P;
     94     return ans%P;
     95 }
     96 
     97 int main(){
     98     scanf("%d%d",&n,&m);
     99     for (int i=1;i<=n;i++){
    100         scanf("%d%d",&a[i].x,&a[i].y);
    101     }
    102     for (int j=1;j<=n;j++){
    103         lst+=Query(MX,a[j].y)-Query(a[j].x,a[j].y);
    104         lst%=P;
    105         Modify(a[j].x,a[j].y);
    106     }
    107     build();
    108     for (int i=1;i<=m;i++){
    109         int x,y,x1,y1,px,py,mn,mx,ny,xy;
    110         ll ans=0;
    111         scanf("%d%d",&x1,&y1);
    112         x=min(x1,y1);
    113         y=max(x1,y1);
    114         px=pos[x],py=pos[y];
    115         if (a[x].x<a[y].x) mn=a[x].x,ny=a[x].y,mx=a[y].x,xy=a[y].y;
    116         else mx=a[x].x,xy=a[x].y,mn=a[y].x,ny=a[y].y;
    117         if (px!=py){
    118             for (int i=x+1;i<st[px+1];i++){
    119                 ans+= (a[i].x>mn)*(a[i].y+ny);
    120                 ans+= (a[i].x<mx)*(a[i].y+xy);
    121 
    122                 ans-= (a[i].x<mn)*(a[i].y+ny);
    123                 ans-= (a[i].x>mx)*(a[i].y+xy);
    124                 ans%=P;
    125             }
    126             for (int i=st[py];i<y;i++){
    127                 ans+= (a[i].x>mn)*(a[i].y+ny);
    128                 ans+= (a[i].x<mx)*(a[i].y+xy);
    129 
    130                 ans-= (a[i].x<mn)*(a[i].y+ny);
    131                 ans-= (a[i].x>mx)*(a[i].y+xy);
    132                 ans%=P;
    133 
    134             }
    135             for (int i=px+1;i<=py-1;i++){
    136                 ans+= query(i,mn,mx,ny,xy);
    137                 ans%=P;
    138             }
    139         }else{
    140             for (int i=x+1;i<y;i++){
    141                 ans+= (a[i].x>mn)*(a[i].y+ny);
    142                 ans+= (a[i].x<mx)*(a[i].y+xy);            
    143 
    144                 ans-= (a[i].x<mn)*(a[i].y+ny);
    145                 ans-= (a[i].x>mx)*(a[i].y+xy);
    146             }
    147                 ans%=P;
    148 
    149         }
    150         if (x!=y) ans+=a[x].y+a[y].y;
    151         ans%=P;
    152         if (a[x].x>a[y].x) ans=(-ans+P)%P;
    153         printf("%lld
    ",lst=(lst+ans+P)%P);
    154         swap(a[x],a[y]);
    155         modify(pos[x]);
    156         modify(pos[y]);
    157     }
    158     return 0;
    159 }
    View Code

    另外当块的大小取sqrt(n)/2的时候跑的飞快。。

    40s就跑出来了。。竟然有rank5(2017.5.27)。。而且空间也很小有没有。。

  • 相关阅读:
    sqlserver tips
    mysql tips
    小知识点集锦
    设计模式
    将微博或者qq空间的说说同步至博客园 wcf+js(ajax)跨域请求(1)
    WCF服务寄宿IIS与Windows服务
    C# 基础小知识之yield 关键字
    WPF命令绑定 自定义命令
    KnockOut 绑定之foreach绑定(mvc+knockout)
    P5019 铺设道路
  • 原文地址:https://www.cnblogs.com/karl07/p/6914234.html
Copyright © 2020-2023  润新知