LOJ535「LibreOJ Round #6」花火-題解
記得開long long,空間要兩倍!
- 題目簡述
給你一個的全排列,相鄰的之間可以任意交換,只有一次可以交換不相鄰的位置的數的機會,求出能讓其排好序的最少交換次數。
分析:
如果沒有那一次不相鄰的交換機會,那麼就是一個求逆序對個數的裸題了。
那麼有了這個之後,我們暴力的想法是列舉的交換情況,每次再計算逆序對個數,總複雜度為,但是顯然過不了。
所以我們考慮,對於一個點,我們可以看作這樣的一個點對,表示下標為,高度為,那麼我們交換的點必須要滿足:,否則會增加逆序對的個數。
而我們將其放在平面上來看,會是這樣的:
紅色的點為,綠色的點為,那麼如果交換這兩個點,我們可以發現,減少的逆序對個數為,因為你原來矩形內的每個點和點會產生逆序對,然後矩形內的點和點產生逆序對,最後點的逆序對,所以交換後就會減少這麼多。
那麼我們只需找到包含點最多的矩形,然後將其左上角的點和右下角的點交換之後答案就為:
為總的逆序對個數,後面是因為開始會減少一個,但是你交換又會增加一步操作,所以是這樣。
我們暴力找的話還是的,但是我們可以發現,對於一個點,如果,那麼用點肯定比點要優秀,因為這兩個矩形是包含的關係,如下圖:
圖上點為點,為點,為點。
同理,對於一個點,如果,那麼肯定比要優秀,如下圖:
點為點,點為點,點為點。
所以根據這個單調性,我們可以用整體二分+主席樹找到包含點最多的矩形,具體細節參考下面這個部落格【Orz-IN】
但是,這個方法是的,所以雖然能過,但是常數巨大且不好寫。
不妨反過來思考。 我們可以對於每一個點,找出包含它的最大的矩形。 那麼我們對於點,我們前面找最小的,且滿足,找後面最大的,且滿足,這個就是能包含它的最大的矩形了,所以對於所有點,只要滿足,那麼這個點就會對其作出貢獻。
我們對於矩形不好處理,所以將其轉化為點對,一個點表示左上角的下標在右下角的下標在的矩形,那麼我們每次只用在內的點加即可。
所以我們用掃描線的思想將一個矩形拆成兩條線,一條入線,一條出線。 我們按照新的平面的座標從下往上掃,所以我們將原來一個點表示的矩形拆為的一條線和的兩條線,當我們遇到第一條線時表示進入了這個矩形,就將加,遇到第二條線就表示已經出了這個矩形,我們要將這個矩形的影響消除,就將減,然後我們每次取當前這條線上的最大值更新最多點矩陣的點數即可,這個可以用一個線段樹維護。
所以先預處理,用歸併排序或者樹狀陣列的方式求出總的逆序對的個數,記最多的點數為,答案就為:
所以在的預處理,的求,回答答案即可。 總複雜度,比分治的要優秀的多。
程式碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=3e5+10;
int n,H[M];
int lmax[M],rmin[M];
struct node{
int l,r,type,ck;
node(){}
node(int a,int b,int c,int d):l(a),r(b),type(c),ck(d){}
bool operator <(const node &a)const{return ck<a.ck||(ck==a.ck&&type>a.type);}
}line[M<<1];//因為每個矩形拆成兩條線,所以空間開兩倍
int tot;
int maxv[M<<2],lazy[M<<2];
void pushup(int o){
maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
}
void pushdown(int o){
if(!lazy[o]) return;
maxv[o<<1]+=lazy[o];
maxv[o<<1|1]+=lazy[o];
lazy[o<<1]+=lazy[o];
lazy[o<<1|1]+=lazy[o];
lazy[o]=0;
}
void update(int o,int l,int r,int L,int R,int v){
if(L<=l&&r<=R){
maxv[o]+=v;lazy[o]+=v;
return;
}
int mid=l+r>>1;
pushdown(o);
if(L<=mid) update(o<<1,l,mid,L,R,v);
if(R>mid) update(o<<1|1,mid+1,r,L,R,v);
pushup(o);
}
//線段樹區間加維護最大值
#define lowbit(a) ((a)&(-(a)))
ll bit[M];
void add(int a,ll b){
for(;a<=n;a+=lowbit(a))bit[a]+=b;
}
ll query(int a){
int ans=0;
for(;a;a-=lowbit(a))ans+=bit[a];
return ans;
}
//樹狀陣列求逆序對個數
ll ans;//記得開long long
void init(){
for(int i=n;i>=1;i--){
ans+=1ll*query(H[i])
相關推薦
LOJ535「LibreOJ Round #6」花火-題解
記得開long long,空間要兩倍!
題目簡述
給你一個nnn的全排列,相鄰的之間可以任意交換,只有一次可以交換不相鄰的位置的數的機會,求出能讓其排好序的最少交換次數。
分析:
如果沒有那一次不相鄰的交換機會,那麼就是一個求逆序對個數的裸題了。
那麼
[決策單調 分治] LOJ#535. 「LibreOJ Round #6」花火
如果 i<ji<j 且 ai>ajai>aj 那麼 ii 作為左端點比 jj 優,右端點同理
那麼搞出兩個上升序列,發現右端點遞增的時候左端點也是單調上升的,也就是gjghfd和vector說的具有決策單調
分治就好了
#inc
loj516 「LibreOJ β Round #2」DP 一般看規律
clear pac ret stdio.h eoj 技術 sort logs targe 傳送門:https://loj.ac/problem/516
【題解】
那段代碼求的是相同的數中間隔最小的值。
離散後用set維護每個值出現次數,每次操作相當於合並兩個set,這步可以
LibreOJ #514. 「LibreOJ β Round #2」模擬只會猜題意
clas oid loj gist mem bsp num clu n) 二次聯通門 : LibreOJ #514. 「LibreOJ β Round #2」模擬只會猜題意
/*
LibreOJ #514. 「LibreOJ β Round #2
LibreOJ #525. 「LibreOJ β Round #4」多項式
cnblogs for getchar 多項式 tps cst row style clu 二次聯通門 : LibreOJ #525. 「LibreOJ β Round #4」多項式
官方題解 :
/*
LibreOJ
LibreOJ #515. 「LibreOJ β Round #2」貪心只能過樣例
tdi thml http column printf name target sum pro
題目描述
一共有 nnn個數,第 iii 個數 xix_ix?i?? 可以取 [ai,bi][a_i , b_i][a?i??,b?i??] 中任意值。設
Loj515 「LibreOJ β Round #2」貪心只能過樣例 - Bitset,Dp
pac namespace als out name c++ 可行性 bsp mes bitset的基本應用了
類似可行性背包的dp考慮
復雜度O(nmL/64)
1 #include <bits/stdc++.h>
2 using namespace s
loj548 「LibreOJ β Round #7」某少女附中的體育課
dft col aps == ret hid 要求 但是 freopen 這道題好神啊!!!
發現這題就是定義了一種新的卷積,然後做k+1次卷積。
這裏我們就考慮構造一個變換T,使得$T(a) \cdot T(b) =T(a°b)$,這裏是讓向量右乘這個轉移矩陣。
於
LOJ #559. 「LibreOJ Round #9」ZQC 的迷宮
AS left str int 交互 stdout block tro flush 一道ZZ結論題,主要是來寫一寫交互題的。
我們要先知道一句話:
扶著墻是肯定可以走出簡單迷宮的。
然後我們冷靜分析問題。若這個迷宮是\(n\times m\)的,那麽最多有\(2mn+n
LOJ565. 「LibreOJ Round #10」mathematican 的二進位制(NTT)
題目連結
https://loj.ac/problem/565
題解
首先,若進行所有操作之後成功執行的運算元為 \(m\),最終得到的數為 \(w\),那麼發生改變的二進位制位的數量之和(即代價之和)為 \(2m - {\rm bit}(w)\)。其中,\({\rm bit}(x)\) 表示 \(x\
「LibreOJ β Round #2」貪心只能過樣例 [bitset]【STL】
題目連結:https://loj.ac/problem/515
——————————————————————————————————
515. 「LibreOJ β Round #2」貪心只能過樣例
記憶體限制:256 MiB 時間限制:1000
#515. 「LibreOJ β Round #2」貪心只能過樣例
解法:記錄 LibreOJ的第一個題,直接bitset暴力即可。
#include <bits/stdc++.h>
using namespace std;
const int max
[暴力]#514. 「LibreOJ β Round #2」模擬只會猜題意
題目梗概
給定一個長度為 n 的序列 A 。
求一個區間的長度不小於x的最大和。
1≤x≤n≤104,0≤m≤105,∣Ai∣≤104。
解題思路
相信我暴力可以過!!!
因為這題僅
「LibreOJ β Round #7」匹配字串
「LibreOJ β Round #7」匹配字串
#520. 「LibreOJ β Round #3」緋色 IOI(開端) 貪心
媽耶,沒臉見人了。巨水,想出來不寫,人生重來算了。
就是個找規律題,相鄰一個連一下,但是我沒注意到是IOI賽制,以為是OI賽制所以沒打,感覺70分好打但是懶得了。。
證明就是把相鄰3個列一下式子就出
[結論] LibreOJ #520. 「LibreOJ β Round #3」緋色 IOI(開端)
題意
戳這裡
題解
這是一道結論題。
我們先把數放到數軸上考慮。定義兩個點的距離為幾何上的距離的平方。
我們可以把一個迴路看作兩條從 1 到 n 的不相交的路徑。
有一種經典的二路取數的 O
2018.09.30【LOJ517】「LibreOJ β Round #2」計算幾何瞎暴力(01Trie)(二進位制拆分)
傳送門
解析:
看到標題的dalaodalaodalao先不要急著錘我。。。
這道題的二進位制拆分和01Trie01Trie01Trie不能混在一起,不要急著說01Trie01Trie01Trie就是二進位制拆分。。。
思路:
這道題可以說是非常好的一道資料結
LOJ #528. 「LibreOJ β Round #4」求和 (莫比烏斯函式)
題意
計算 ∑i=1n∑j=1mμ2(gcd(i,j))∑i=1n∑j=1mμ2(gcd(i,j)) (mod(mod 998244353)998244353)
題解
∑d=1nμ2(d)
LibreOJ #517.「LibreOJ β Round #2」計算幾何瞎暴力 字典樹
題意
有一個長度為n的陣列a和m個操作,每個操作形如
1 x在序列的末尾新增一個數x
2 l r詢問[l,r]的數的和
3 x把序列中所有數都異或上x
4把序列中所有數從小到大排序
n,m≤105,x,ai≤109n,m≤105,x,ai≤109
#516. 「LibreOJ β Round #2」DP 一般看規律 set啟發式合併
題意:給出操作,將序列中所有一個數字替換為另一個,詢問每次操作後距離最近的兩個相同數字的距離。
解法:每個數字只與他的前驅和後繼產生貢獻。構建n個set,每次將較小的暴力合併到大的上面,通過lower_bound來找到他的前驅和後繼。懶得離散化可以用map