不僅讓ssw02考場自閉,而且改的ssw02也差點自閉,改了ssw02乙個停課的下午
ssw02很少寫動態開點的啊
description毒瘤的線段樹操作
input
從檔案multiset.in 中讀入資料。
第一行兩個正整數n; q, 表示集合個數和詢問數量。
接下來q 行,首先是乙個整數opt:
若opt = 1,接下來三個整數l; r; x,表示向編號[l; r] 的集合中加入x。
若opt = 2,接下來兩個整數l; r,表示詢問編號[l; r] 的集合的元素個數和。
output
輸出到檔案multiset.out 中。
對於每個詢問,輸出一行乙個整數,表示答案。
in.1
4 41 1 2 1
1 1 2 2
1 1 4 1
2 1 4
out.1
10資料範圍與約定
對於20% 資料,n 500;m 500,資料隨機。
對於另10% 資料,所有1 操作的x 均不相同。
對於另20% 資料,所有1 操作的x 均相同。
對於另20% 資料,x 20。
對於另10% 資料,1 操作的l = r。
對於100% 資料,1 n; q 200000,1 opt 2,1 l r n,1 x n。
思考部分分暴力打好點可以最多拿70(ssw02意思是線段樹+暴力)
如果讓每個點記錄加過的數,那麼空間是肯定不夠的。如果考慮用每乙個加過的數來記錄加過的區間,那麼就有了思路。
我們嘗試開 n 棵樹來記錄每個點覆蓋的區間,當然不能直接建樹,否則會浪費大量空間。
每一次加數操作或者查詢操作都是乙個區間,如果動態開點最多隻會開 2logn 個點 ,空間複雜度不會超過 k nlogn ( k為乙個不大的2位數的常數 )。
處理:
1.每次增加操作時,判斷該區間是否被完全覆蓋,否則接著分。同時還要記錄是否開點(動態開點線段樹基操)。
然後判斷是應當加還是乘(分至乙個完全覆蓋區間)
if( !p )p = ++cnt ;
int mid = ( l+r )>>1 ;
if( l >= x && r <= y )
else if( !t[ p ].w )
else
} pushdown( p , l , r ) ;
if( x <= mid )change_s( t[ p ].ls , l , mid , x , y ) ;
if( y > mid )change_s( t[ p ].rs , mid+1 , r , x , y ) ;
t[ p ].w = t[ t[p].ls ].w + t[ t[p].rs ].w ;
2.開點下傳判定(接上)
void pushdown( int p , int l , int r )
}
3.然後就是區間加,區間乘,區間求和
void mul( int p , int l , int r , int x , int y , int val )
spread( p ) ;
int mid = ( l+r )>>1 ;
if( x <= mid )mul( t[ p ].ls , l , mid , x , y , val ) ;
if( y > mid )mul( t[ p ].rs , mid+1 , r , x , y , val ) ;
//if( wrong == 5 )cout<>1 ;
if( x <= mid )add( t[ p ].ls , l , mid , x , y , val ) ;
if( y > mid )add( t[ p ].rs , mid+1 , r , x , y , val ) ;
t[ p ].sum = t[ t[p].ls ].sum + t[ t[p].rs ].sum ;
}
#includeusing namespace std ;
const int maxn = 200005 ;
const long long mod = 998244353 ;
#define ll long long
inline int read()
struct segt[ maxn*30 ];
int n , q , cnt = 0 , root[ maxn ] , wrong = 0 ;
void build( int &p , int l , int r )
int mid = ( l+r )>>1 ;
build( t[ p ].ls , l , mid ) , build( t[ p ].rs , mid+1 , r ) ;
}void spread( int p )
if( t[ p ].add )
}void mul( int p , int l , int r , int x , int y , int val )
spread( p ) ;
int mid = ( l+r )>>1 ;
if( x <= mid )mul( t[ p ].ls , l , mid , x , y , val ) ;
if( y > mid )mul( t[ p ].rs , mid+1 , r , x , y , val ) ;
//if( wrong == 5 )cout<>1 ;
if( x <= mid )add( t[ p ].ls , l , mid , x , y , val ) ;
if( y > mid )add( t[ p ].rs , mid+1 , r , x , y , val ) ;
t[ p ].sum = t[ t[p].ls ].sum + t[ t[p].rs ].sum ;
}void pushdown( int p , int l , int r )
}void change_s( int &p , int l , int r , int x , int y )
else if( !t[ p ].w )
else
} pushdown( p , l , r ) ;
if( x <= mid )change_s( t[ p ].ls , l , mid , x , y ) ;
if( y > mid )change_s( t[ p ].rs , mid+1 , r , x , y ) ;
t[ p ].w = t[ t[p].ls ].w + t[ t[p].rs ].w ;
}ll ask( int p , int l , int r , int x , int y )
void check( int p , int l , int r )
int main()
else printf("%lld\n",ask( root[ 0 ] , 1 , n , m2 , m3 ) ) ;
} return 0 ;
}
python中神奇的集合
從上節學習過字串後,心中就在思考,想要儲存多個字串怎麼辦?c中有陣列可以實現上述功能,那python呢?現在就讓我們來一 竟吧。python中提供了一種神奇的資料型別list,他有多神奇呢,大家先不要急,讓我婉婉到來,茶要慢慢品嘛。list是一種有序的集合,可以隨時對他進行增減等操作。比如需要列出小...
集合劃分 題解
這道題思路挺清奇的。屬於那種既考演算法模板又考思維的一類題。看到乙個點,可以放在 a 或 b 兩個集合,就要聯想到2 sat問題。這道題如果只讓判斷是否存在合法方案,並輸出任意一種方案,那這題就屬於2 sat問題的模板。但是這題比較難的一點就是求方案數。一般的2 sat問題能不能求方案數呢?我在網上...
集合選數題解
構造神題,對於每乙個不含質因數2和3的數字,我們構造乙個矩陣 可能並不滿 第一行第一列是這個數,在同一行中,下一列的數是這一列的數的2倍,在同一列中,下一行的數是這一行的數的3倍。如果我們選矩陣中乙個數,則右邊的數是這個數的兩倍而不能選,同理,下面的數同樣不能選,不能選左邊的數,因為這個數是它的兩倍...