BZOJ3295 CQOI2011 動態逆序對

来源:http://www.cnblogs.com/fenghaoran/archive/2017/07/31/7266176.html
-Advertisement-
Play Games

3295: [Cqoi2011]動態逆序對 Description 對於序列A,它的逆序對數定義為滿足i<j,且Ai>Aj的數對(i,j)的個數。 給1到n的一個排列,按照某種順序依次刪除m個元素。 你的任務是在每次刪除一個元素之前統計整個序列的逆序對數。 對於序列A,它的逆序對數定義為滿足i<j, ...


3295: [Cqoi2011]動態逆序對

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

對於序列A,它的逆序對數定義為滿足i<j,且Ai>Aj的數對(i,j)的個數。 給1到n的一個排列,按照某種順序依次刪除m個元素。 你的任務是在每次刪除一個元素之前統計整個序列的逆序對數。

Input

輸入第一行包含兩個整數nm,即初始元素的個數和刪除的元素個數。 以下n行每行包含一個1到n之間的正整數,即初始排列。 以下m行每行一個正整數,依次為每次刪除的元素。

Output 

輸出包含m行,依次為刪除每個元素之前,逆序對的個數。

Sample Input

5 4

1 5 3 4 2

5 1 4 2

 

Sample Output

5
2
2
1
樣例解釋
(1,5,3,4,2) (1,3,4,2) (3,4,2) (3,2) (3)。

HINT 

N<=100000 M<=50000

  表示當時沒看出來是CDQ,樹套樹倒是瞄出來了,只是不會寫啊。

  現在看來還是很顯然的。

  對於排列中的數,記它被刪除的時間為t(未刪除的設為m+1),下標為X,大小為Y。

  那麼對於一個數i,來看在它前面被刪除的數對它的答案的減小值為多少:

    Σ(Tj<Ti && Xj<Xi && Yj>Yi) + Σ(Tj<Ti && Xj>Xi && Yj<Yi)

  做兩次CDQ就好了。這種沒有重覆的算起來真是爽啊。

  做的時候沒有草稿紙真TM不爽。

#include    <iostream>
#include    <cstdio>
#include    <cstdlib>
#include    <algorithm>
#include    <vector>
#include    <cstring> 
using namespace std;
 
const int N = 100010;
struct Data{
    int X,Y,T;long long len;
    bool operator <(const Data &t)const{
        return T<t.T;
    }
}rem[N],f[N],t[N];
int n,m,ban[N],bplace[N],A[N],T[N];
long long Ans,ans[N];
 
inline int gi()
{
    int x=0,res=1;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')res=-res;ch=getchar();}
    while(ch>'/' && ch<':')x=x*10+ch-48,ch=getchar();
    return x*res;
}
 
inline int lb(int k){return k&-k;}
 
inline void update(int x){for(;x<=n;x+=lb(x))T[x]++;}
 
inline int query(int x)
{
    int ans=0;
    for(;x;x-=lb(x))ans+=T[x];
    return ans;
}
 
inline void clean(int x){for(;x<=n;x+=lb(x))T[x]=0;}
 
inline void calc()
{
    memset(T,0,sizeof(T));Ans=0;
    for(int i=1;i<=n;++i){
        Ans+=(i-query(A[i])-1);
        update(A[i]);
    }
    memset(T,0,sizeof(T));
}
//在外面保證T有序,CDQ內保證X有序,統計Y值。 
//T:時間 X:位置 Y:權值
//CDQ calc Ti<Tj Xi<Xj Y[i]<Y[j]
inline void CDQ(int l,int r)
{
    if(l==r)return;int mid=(l+r)>>1;
    CDQ(l,mid);CDQ(mid+1,r);
    int x=l,y=mid+1,z=l;
    while(x<=mid && y<=r)
        if(f[x].X<f[y].X)update(f[x].Y),t[z++]=f[x++];
        else f[y].len+=query(f[y].Y),t[z++]=f[y++];
    while(x<=mid)t[z++]=f[x++];
    while(y<=r)f[y].len+=query(f[y].Y),t[z++]=f[y++];
    for(int i=l;i<=mid;++i)clean(f[i].Y);
    for(int i=l;i<=r;++i)f[i]=t[i];
}
 
int main()
{
    n=gi();m=gi();
    for(int i=1;i<=n;++i)
        A[i]=gi();
    for(int i=1;i<=m;++i)
        bplace[ban[i]=gi()]=i;
    for(int i=1;i<=n;++i){
        rem[i].T=bplace[A[i]];
        rem[i].X=i;
        rem[i].Y=A[i];
        if(!rem[i].T)rem[i].T=m+1;
    }
    sort(rem+1,rem+n+1);calc();
    for(int i=0;i<=m;++i)ans[i]=Ans;
    for(int i=1;i<=n;++i){
        f[i]=rem[i];
        f[i].Y=n-f[i].Y+1;
    }
    reverse(f+1,f+n+1);
    CDQ(1,n);sort(f+1,f+n+1);
    for(long long i=1,s=0;i<=n;++i){
        if(!f[i].T)continue;
        ans[f[i].T]-=s;s+=f[i].len;
    }
    for(int i=1;i<=n;++i){
        f[i]=rem[i];
        f[i].X=n-f[i].X+1;
    }
    reverse(f+1,f+n+1);
    CDQ(1,n);sort(f+1,f+n+1);
    for(long long i=1,s=0;i<=n;++i){
        if(!f[i].T)continue;
        ans[f[i].T]-=s;s+=f[i].len;
    }
    for(int i=1;i<=m;++i)
        printf("%lld\n",ans[i]);
    return 0;
}

  

  然後看見我在上古時期的分塊??!!

  一臉懵逼。

  瞪了好久發現 不是我寫的。

  大概思想就是分塊,每塊內排序。

  然後查詢:

  不在自己塊里的,二分一下。

  在自己塊里的,暴力搞搞。

  然後刪掉。

  6000ms...過去了...

  昂波利污波。

#include <cstdio>  
#include <cmath>  
#include <cstdlib>  
#include <algorithm>  
#include <cstring>  
using namespace std;  
#define ll long long  
const int N=200050;  
int n,m,a[N];  
int tmp[N],t[N];//merge-sort  
int belong[N],L[N],R[N],cnt,k,x,y;  
int ad[N];      //i在原數列中的位置為ad[i]    
int b[N];       //每個塊維護有序數列   
int sum[N];     //當前塊中刪除了多少個數   
int adx;  
int i;  
bool f[N];  
ll tot;        //當前逆序對數               開 long long !   
inline int get(){  
  int p=0;char x=getchar();  
  while (x<'0' || x>'9') x=getchar();  
  while (x>='0' && x<='9') p=p*10+x-'0',x=getchar();  
  return p;  
}  
inline void merge_sort(int l,int r){  
  int mid,p,i,j;  
  mid=(l+r)>>1;  
  i=p=l;j=mid+1;  
  while (i<=mid && j<=r)  
    if (tmp[i]>tmp[j]) t[p++]=tmp[j++],tot+=mid-i+1;  
    else t[p++]=tmp[i++];  
  while (i<=mid) t[p++]=tmp[i++];  
  while (j<=r) t[p++]=tmp[j++];  
  for (i=l;i<=r;i++) tmp[i]=t[i];  
  return ;  
}  
inline void merge(int l,int r){  
  if (l>=r) return ;  
  int mid=(l+r)>>1;  
  merge(l,mid);  
  merge(mid+1,r);  
  merge_sort(l,r);  
  return ;  
}  
void init(){  
  n=get();m=get();  
  k=sqrt(n);      //塊大小   
  cnt=n/k;if (n%k) cnt++; //塊個數   
  for (int i=1;i<=n;i++)  
    a[i]=get(),ad[a[i]]=i,belong[i]=(i-1)/k+1;  
  for (int i=1;i<=cnt;i++)  
    L[i]=i*k-k+1,R[i]=i*k;  
  R[cnt]=n;  
  memcpy(tmp,a,sizeof tmp); 
  tot=0;  
  merge(1,n);  
  memcpy(b,a,sizeof a);  
  for (int i=1;i<=cnt;i++)  
    sort(b+L[i],b+R[i]+1);  
  memset(f,1,sizeof f);  
  return ;  
}  
inline int search(int t,int p){  
  int l,r,ret;  
  l=L[t]; r=R[t]; ret=R[t];  
  while (l<=r){  
    int mid=(l+r)>>1;  
    if (b[mid]<=p) ret=mid,l=mid+1;  
    else r=mid-1;  
  }  
  if (b[ret]>p) ret=L[i]-1;  
  return ret;  
}  
int main(){
  init();  
  for (int p=1;p<=m;p++){  
    printf("%lld\n",tot);  
    y=get();x=ad[y];        //得到在a數列中的位置 所處的塊的編號肯定不變  
    k=belong[x];            //x屬於第k個塊     
    for (i=1;i<k;i++)  
      tot-=R[i]-search(i,a[x]);  
    for (i=k+1;i<=cnt;i++)  
      tot-=search(i,a[x])-L[i]+1-sum[i];  
    for (i=L[k];i<x;i++)  
      if (f[a[i]] && a[i]>a[x]) tot--;  
    for (i=x+1;i<=R[k];i++)  
      if (f[a[i]] && a[i]<a[x]) tot--;  
    adx=search(k,a[x]);  
    b[adx]=0;sum[k]++;  
    f[a[x]]=0;  
    sort(b+L[k],b+R[k]+1);  
  }  
  return 0;  
}

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • IdentityServer4 是一個提供 認證服務,單點登錄/登出(SSO),API訪問控制,聯合認證通道的可定製、免費商業支持的框架。 ...
  • IdentityServer4 是一個提供 認證服務,單點登錄/登出(SSO),API訪問控制,聯合認證通道的可定製、免費商業支持的框架。 ...
  • 非同步非常重要的一點就是不會使當前線程阻塞,C#主要通過委托機制來實現非同步編程。 ...
  • 公司的核心業務合作伙伴淘寶網,最近出現泄漏用戶信息的現象,找了好久找不到根源,於是乎,淘寶那邊決定對所有敏感數據進行加密,從出口和入口都走密文,於是乎,我們的工作量就來了。 我們的一個底單資料庫,存儲了大量淘寶賣家和買家的訂單列印,申請單號,發貨,回收單號等等操作的日誌,大概有10億左右數據(自動刪 ...
  • 考慮使用靜態工廠方法代替構造器 類可以提供一個公有的靜態工廠方法(public static factory method)來返回一個類的實例。例如,Boolean類的valueOf()方法: public static Boolean valueOf(boolean b) { return (b ...
  • 1. 心得體會 1.1 線程 寫代碼時,需要至少考慮兩個問題:UI線程與子線程。 UI線程:主要處理UI線程的事情(這不是廢話嗎?) 子線程:主要做網路連接、回調、文件IO等操作。 備註:UI線程不能夠被阻塞,不然會有ANR問題。 1.2 界面 寫代碼時,不要貪圖方便在xml中用一個ViewPage ...
  • JSP製作簡單登陸界面 運行環境 eclipse+tomcat+MySQL 不知道的可以參考Jsp運行環境——Tomcat 項目列表 這裡我先把jsp文件先放在Web-INF外面訪問 代碼演示: index.jsp就好像一般網站的首頁一樣感覺,將header.jsp和footer.jsp引入其中 h ...
  • Map數據結構的使用 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...