主頁 >  其他 > P9376 題解

P9376 題解

2023-05-31 08:37:56 其他

首先考慮怎么暴力,

考慮把每個數進行 \(B\) 進制分解,然后我們驚奇的發現這兩個操作就是把最低位去掉和往最低位后面插入一個數,

然后我們順藤摸瓜,把每個數的分解扔到 Trie 樹上,我們發現我們要找到一個節點,使得所有單詞節點到其的距離之和最短,答案就是這個最短距離,

這里直接考慮一個 Trie 樹上 dp,記所有單詞節點到節點 \(i\) 的最短距離為 \(dp_i\),然后直接去轉移,

然后考慮找找性質,

\(sz_i\) 表示以節點 \(i\) 為根的子樹內單詞節點數量,我們發現節點 \(i\) 的轉移如下 \(dp_i = dp_{fa_i} - sz_j + (sz_1 - sz_j)\)

又因為 \(sz_i \leq sz_{fa_i}\),所以只有當節點 \(i\) 滿足 \(sz_i \times 2 > sz_1\) 進入到以 \(i\) 為根的子樹轉移才最優,

而我們又發現對于一個節點滿足條件的子節點至多只有 \(1\)

也就是說如果把最優答案在樹上的轉移畫出來,并稱其為最優路徑,那么首先這一定是一條從根出發的路徑,而且以這條路徑所代表的數為前綴的數一定超過總數的一半

然后有兩種優化方向,

第一種是利用可持久化 Trie 樹預處理,然后直接在 Trie 上利用剛剛的性質暴力 \(\log_{B} V\) 查詢,缺點是對于每個 \(B\) 都要建一棵樹,

第二種是因為我們只在乎最優路徑上的轉移,所以我們隨機抽取 \(\log n\) 個節點放到 Trie 樹上,顯然因為這個性質類似于絕對眾數的性質,因此最優的轉移路徑不在 Trie 上出現的可能只有 \(\frac{1}{n}\),那么多抽取幾個節點就可以基本保證一定會出現,

那么轉移路徑找出來了,現在問題是轉移中 \(sz_i\) 怎么求?

我們有發現 \(sz_i\) 等價于 \(B\) 進制下以從根節點到節點 \(i\) 所表示的數為前綴的數的數量,而這個可以列舉這個前綴后面有幾位數轉變成一個連續區間上查詢權值為 \([L,R]\) 的數的數量,這個可以直接主席樹來搞,這么做缺點是復雜度是 \(n \log_{B}^3 V\)

考慮到 \(\log_{2} n\) 一般遠大于 \(\log_{3} n\)

所以結合兩種演算法,用第一種演算法解決 \(B = 2\) 的詢問,用第二種演算法解決其他詢問,

那么就做完了,

代碼極丑,慎入,

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int top = 100000001;
const int maxn = 1e6+114;
struct Node{
    int sz;//當前這個節點子樹內有多少個單詞節點
    vector <pair<int,int> > edge;//邊
}Trie[maxn];
struct node{
    int sz;
    int ls,rs;
}_01trie[maxn*30];
struct NODE{
    int val;
    int ls,rs;
}SGTtree[maxn*30];
int SGTroot[maxn];
int SGTtot=1;
int SGTask(int ql,int qr,int lt,int rt,int L,int R){
    if(rt<ql||lt>qr){
        return 0;
    }
    if(ql<=lt&&rt<=qr){
        return SGTtree[R].val-SGTtree[L].val;
    }
    int mid=(lt+rt)/2;
    int res=0;
    res+=SGTask(ql,qr,lt,mid,SGTtree[L].ls,SGTtree[R].ls);
    res+=SGTask(ql,qr,mid+1,rt,SGTtree[L].rs,SGTtree[R].rs);
    return res;
}
int SGTquery(int l,int r,int cl,int cr){
    return SGTask(cl,cr,1,top,SGTroot[l-1],SGTroot[r]);
}
void SGTupdate(int cur,int lst,int lt,int rt,int pos,int v){
    SGTtree[cur].val=SGTtree[lst].val+v;
    if(lt==rt){
        return ;
    }
    int mid=(lt+rt)/2;
    if(pos<=mid){
        SGTtree[cur].rs=SGTtree[lst].rs;
        SGTtree[cur].ls=++SGTtot;
        SGTupdate(SGTtree[cur].ls,SGTtree[lst].ls,lt,mid,pos,v);
    }
    else{
        SGTtree[cur].ls=SGTtree[lst].ls;
        SGTtree[cur].rs=++SGTtot;
        SGTupdate(SGTtree[cur].rs,SGTtree[lst].rs,mid+1,rt,pos,v);
    }
}
int qpow(int a,int b){
    if(b==0) return 1;
    if(b==1) return min(a,top);
    int res=min(qpow(a,b/2),top);
    res=min(top,res*res);
    if(b%2==1) res=min(res*a,top);
    return min(top,res);
}
void SGTadd(int pos,int val){
    SGTroot[pos]=++SGTtot;
    SGTupdate(SGTroot[pos],SGTroot[pos-1],1,top,val,1);
}
int SUMQUERY(int B,int L,int R){//查詢 B 進制下區間 [L,R] 所有數長度之和 
    int res=0;
    for(int k=1;k<=30;k++){
        int l=min(top,qpow(B,k-1)),r=min(top,qpow(B,k)-1);
        res+=SGTquery(L,R,l,r)*k;
        if(r==top) break;
    }
    return res;
}
int PREQUERY(int x,int B,int L,int R){//查詢 B 進制下區間 [L,R] 內多少個數前綴為 x
    int res=0;
    for(int k=0;k<=30;k++){
        int l=min(top,x*qpow(B,k)),r=min(top,(x+1)*qpow(B,k)-1);
        res+=SGTquery(L,R,l,r);
        if(r==top) break;
    }
    return res;
}
int tot=1,anser;
int _01tot=1;
int sum;
int n,m;
int flag;
stack<int> s;
int root[maxn],Sum[maxn];
void _01insert(int cur,int lst){
    _01trie[cur].sz++;
    s.pop();
    if(s.size()==0) return ;
    if(s.top()==0){
        _01trie[cur].rs=_01trie[lst].rs;
        _01trie[cur].ls=++_01tot;
        _01trie[_01trie[cur].ls].sz+=_01trie[_01trie[lst].ls].sz;
        _01insert(_01trie[cur].ls,_01trie[lst].ls);
    }
    else{
        _01trie[cur].ls=_01trie[lst].ls;
        _01trie[cur].rs=++_01tot;
        _01trie[_01trie[cur].rs].sz+=_01trie[_01trie[lst].rs].sz;
        _01insert(_01trie[cur].rs,_01trie[lst].rs);
    }
}
void _01dfs(int l,int r,int ans,int L,int R){
    if(l==0&&r==0) return ;
    anser=min(anser,ans);
    if(_01trie[_01trie[r].ls].sz-_01trie[_01trie[l].ls].sz>_01trie[_01trie[r].rs].sz-_01trie[_01trie[l].rs].sz){
        _01dfs(_01trie[l].ls,_01trie[r].ls,ans-(_01trie[_01trie[r].ls].sz-_01trie[_01trie[l].ls].sz)+(_01trie[R].sz-_01trie[L].sz-(_01trie[_01trie[r].ls].sz-_01trie[_01trie[l].ls].sz)),L,R);
    }
    else{
        _01dfs(_01trie[l].rs,_01trie[r].rs,ans-(_01trie[_01trie[r].rs].sz-_01trie[_01trie[l].rs].sz)+(_01trie[R].sz-_01trie[L].sz-(_01trie[_01trie[r].rs].sz-_01trie[_01trie[l].rs].sz)),L,R);
    }
}
int _01query(int l,int r){
    anser=INT_MAX;
    _01dfs(root[l-1],root[r],Sum[r]-Sum[l-1],root[l-1],root[r]);
    return anser;
}
void _01add(int x,int B,int pos){
    while(x!=0){
        s.push(x%B);
        x/=B;
    }
    s.push(0);
    Sum[pos]=s.size()-1+Sum[pos-1];
    root[pos]=++_01tot;
    _01trie[root[pos]].sz+=_01trie[root[pos-1]].sz;
    _01insert(root[pos],root[pos-1]);
}
void insert(int cur,int val){
    Trie[cur].sz+=val;
    s.pop();
    if(s.size()==0) return ;
    for(pair<int,int> v:Trie[cur].edge){
        if(v.second==s.top()){
            insert(v.first,val);
            return ;
        }
    }
    Trie[cur].edge.push_back(make_pair(++tot,s.top()));
    insert(tot,val);
}
void add(int x,int B){
    while(x!=0){
        s.push(x%B);
        x/=B;
    }
    s.push(0);
    sum+=s.size()-1;
    insert(1,1);
}
void dfs(int cur,int ans,int PRE,int S,int B,int L,int R){
    anser=min(anser,ans);
    for(pair<int,int> v:Trie[cur].edge){
        int nxt=PRE*B+v.second;
        int g=PREQUERY(nxt,B,L,R);
        if((S-g)-g>=0) continue;
        dfs(v.first,ans-g+(S-g),nxt,S,B,L,R);
    }
}
int query(int B,int L,int R){
    anser=INT_MAX;
    dfs(1,SUMQUERY(B,L,R),0,(R-L+1),B,L,R);
    return anser;
}
void clear(){
    for(int i=1;i<=tot;i++){
        Trie[i].edge.clear();
        Trie[i].sz=0;
    }
    sum=0;
    tot=1;
}
int a[maxn];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
            cin>>a[i];
            SGTadd(i,a[i]);
            _01add(a[i],2,i);
    }       
    while(m--){
        int l,r,B;
        cin>>l>>r>>B;
        if(B==2){
            cout<<_01query(l,r)<<"\n";
        }
        else{
        clear();
        for(int j=1;j<=22;j++){
            int x=rand()%(r-l+1)+l;
            add(a[x],B);
        }
        cout<<query(B,l,r)<<'\n';
        }
    }            
}
/*
5 2
7 6 5 8 9
1 3 2
2 5 2
*/

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/553870.html

標籤:其他

上一篇:AtCoder Beginner Contest 303

下一篇:返回列表

標籤雲
其他(160034) Python(38189) JavaScript(25464) Java(18161) C(15234) 區塊鏈(8268) C#(7972) AI(7469) 爪哇(7425) MySQL(7217) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5344) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4579) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1977) 功能(1967) Web開發(1951) HtmlCss(1950) C++(1927) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1878) .NETCore(1862) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • P9376 題解

    首先考慮怎么暴力。 考慮把每個數進行 $B$ 進制分解,然后我們驚奇的發現這兩個操作就是把最低位去掉和往最低位后面插入一個數。 然后我們順藤摸瓜,把每個數的分解扔到 Trie 樹上,我們發現我們要找到一個節點,使得所有單詞節點到其的距離之和最短,答案就是這個最短距離。 這里直接考慮一個 Trie 樹 ......

    uj5u.com 2023-05-31 08:37:56 more
  • AtCoder Beginner Contest 303

    ## [A - Similar String (abc303 a)](https://atcoder.jp/contests/abc303/tasks/abc303_a) ### 題目大意 給定兩個字串,問這兩個字串是否相似。 兩個字串相似,需要每個字母,要么完全相同,要么一個是`1`一個是` ......

    uj5u.com 2023-05-31 08:37:52 more
  • Kali滲透Windows服務器

    這個實驗主要讓我們學習漏洞掃描技識訓本原理,了解其在網路攻防中的作用,掌握使用Kali中的Metasploit對目標主機滲透,并根據報告做出相應的防護措施。 ......

    uj5u.com 2023-05-31 08:37:31 more
  • 輔助測驗和研發人員的一款小插件【資料安全】

    ## 一、為什么要做一款這樣的小插件 資料,一直在思考如何讓資料更安全的流轉和服務于客戶,圍繞這樣的想法,我們做過許多方面的擴展。我們落地了服務端的資料切片支持場景化的設計,實作了基于JDBC協議對SQL的攔截與切片,實作了在應用層的全鏈路資料庫審計方案和實作,實作了WEB端明暗水印和檔案水印等等, ......

    uj5u.com 2023-05-31 08:37:14 more
  • 機器學習-KNN演算法

    ##### 1. 演算法原理(K-Nearest Neighbor) - 本質是通過距離判斷兩個樣本是否相似,如果距離夠近就認為他們足夠相似屬于同一類別 - 找到離其最近的 k 個樣本,并將這些樣本稱之 為「**近鄰**」(nearest neighbor)。 - 對這 k 個近鄰,查看它們的都屬于何 ......

    uj5u.com 2023-05-31 08:37:10 more
  • 【智能軟體安全】上海道寧為您帶來智能軟體安全平臺——?Veracod

    Veracode可以全面地 保護您構建和管理地應用程式 在現代軟體 開發生命周期的 每個階段不斷發現并修復缺陷 Veracode通過 建立一種在安全和開發團隊之間 架起橋梁并授權 開發人員成為 安全倡導者的積極文化 從一開始就防止常見的安全漏洞 開發商介紹 Veracode成立于2006年,起初是一 ......

    uj5u.com 2023-05-31 08:36:56 more
  • 百度飛槳(PaddlePaddle) - PP-OCRv3 文字檢測識別系統 基于 Padd

    [toc] [百度飛槳(PaddlePaddle) - PP-OCRv3 文字檢測識別系統 預測部署簡介與總覽](https://www.cnblogs.com/vipsoft/p/17439619.html) [百度飛槳(PaddlePaddle) - PP-OCRv3 文字檢測識別系統 Padd ......

    uj5u.com 2023-05-31 08:36:42 more
  • 牛客小白月賽73

    # A.最小的數字 ### 題目: ![](https://img2023.cnblogs.com/blog/2960080/202305/2960080-20230526220648535-777334559.png) ### 分析: 簡單列舉一下,找到第一個大于等于n的且是3的倍數的數 ### ......

    uj5u.com 2023-05-31 08:36:21 more
  • 詳解RocketMQ 順序消費機制

    摘要:順序訊息是指對于一個指定的 Topic ,訊息嚴格按照先進先出(FIFO)的原則進行訊息發布和消費,即先發布的訊息先消費,后發布的訊息后消費。 本文分享自華為云社區《RocketMQ 順序消費機制》,作者: 勇哥java實戰分享 。 順序訊息是指對于一個指定的 Topic ,訊息嚴格按照先進先 ......

    uj5u.com 2023-05-31 08:35:55 more
  • 隱私合規相關法律法規合集

    01中華人民共和國網路安全法(全文)201611.pdf 02資訊安全技術 個人資訊安全規范GB:T 35273—2017.pdf 03開展App違法違規收集使用個人資訊專項治理-中共中央網路安全和資訊化委員會辦公室201901.pdf 04App違法違規收集使用個人資訊自評估指南201903.pd ......

    uj5u.com 2023-05-31 08:35:46 more