徐寅展**裡的題
為了敘述方便,不妨稱題目中初始給出的賦值操作為第一類操作,賦值操作因為會直接覆蓋前面操作的貢獻,所以有一定的時間作用區間,那麼按時間作用區間處理後得到新的操作,不妨稱之為第二類操作。
考慮用線段樹先模擬一遍,乙個標記會把原來在它子樹中的操作無效化,記得下推標記時要把標記**。但是這樣的運算元就達到了o(m
logn)
o(m\log n)
o(mlogn)
。但如果仔細分析,以操作塊數作為勢能函式,那麼每個操作頂多增加2的勢能,所以總的勢能其實是o(m
)o(m)
o(m)
的。因此要把子樹中相同的操作合併起來。收集標記可以暴力dfs,勢能分析可證複雜度上限為o(m
log2n
)o(m\log^2 n)
o(mlog2n
)。經過處理後的第二類操作,如果在時間線段樹上有交集,則他們必定在空間上無交集。把第二類操作打到時間線段樹上去。那麼怎麼處理詢問呢,整體二分??然後複雜度又變成o(m
log3n
)o(m\log^3 n)
o(mlog3n
)的了有乙個巧妙的處理方法,詢問是乙個葉子上的,它的答案都是到根的路徑上的操作做的貢獻,那麼我們就摒棄以前字首和的方法,單獨考慮每個節點。考慮把詢問加入到葉子到根上所有點中去,如果我們把每個節點中的操作按照權值排序,那麼就只需要用乙個資料結構支援區間加和區間求和了!所有的修改和詢問總的複雜度為o(m
log2n
)o(m\log^2 n)
o(mlog2n
)。綜上,時間複雜度為o(m
log2n
)o(m\log^2 n)
o(mlog2n
)。好久沒打過行數100+的**了,又有了之前做資料結構碼農題時的那種欲生欲死的感覺…
#include
#include
#include
#define lowbit(x) ((x)&(-(x)))
using
namespace std;
typedef
long
long ll;
const
int maxn=
100010
;template
<
typename tp>
inline
intgetmin
(tp &x,tp y)
template
<
typename tp>
inline
intgetmax
(tp &x,tp y)
template
<
typename tp>
inline
void
read
(tp &x)
int n,m,tm,oc,qc,stk[maxn]
,ans[maxn]
;struct oper
oper operator+(
const oper &t)
const
}q[maxn<<1]
,qy[maxn]
;struct bit
ll query
(int p)
}bit;
struct time_sgt
int m=
(l+r)
>>1;
if(l<=m)
update
(l,m,l,r,rt<<
1,t);if
(mupdate
(m+1
,r,l,r,rt<<1|
1,t);}
void
addq
(int l,
int r,
int pos,
int rt,oper t)
void
dfs(
int l,
int r,
int rt)
for(itr=op[rt]
.begin()
;itr!=op[rt]
.end()
;++itr)if(
!itr-
>op)
bit.
add(itr-
>l,-1
),bit.
add(itr-
>r+1,
1);if
(l==r)
return
;int m=
(l+r)
>>1;
dfs(l,m,rt<<1)
;dfs
(m+1
,r,rt<<1|
1);}
}t;struct sgt
;getmin
(tmp[rt<<1]
.r,m)
;getmax
(tmp[rt<<1|
1].l,m+1)
;}void
build
(int l,
int r,
int rt)
int m=
(l+r)
>>1;
build
(l,m,rt<<1)
;build
(m+1
,r,rt<<1|
1);}
void
dfs(
int l,
int r,
int rt);}
if(l==r)
int m=
(l+r)
>>
1;sz[rt]=0
;dfs
(l,m,rt<<1)
;dfs
(m+1
,r,rt<<1|
1);}
void
update
(int l,
int r,
int l,
int r,
int rt,oper t)
int m=
(l+r)
>>1;
if(tag[rt]
)pushdown
(l,m,r,rt);if
(l<=m)
update
(l,m,l,r,rt<<
1,t);if
(mupdate
(m+1
,r,l,r,rt<<1|
1,t)
; sz[rt]
=sz[rt<<1]
|sz[rt<<1|
1]|tag[rt];}
}sgt;
void
input()
sgt.
build(1
,n,1);
for(
int i=
1;i<=m;i++
);now=sgt.xu[1]
;for
(int j=
2;j<=sgt.cnt;j++)}
if(op==2)
} sgt.cnt=
0;sgt.
dfs(
1,n,1)
;sgt.xu[
++sgt.cnt]
=(oper)
;now=sgt.xu[1]
;for
(int j=
2;j<=sgt.cnt;j++
)for
(int i=
1;i<=qc;i++
) t.
addq(1
,n+m,qy[i]
.tm,
1,qy[i]);
}int
main()
問題 A 乙個簡單的整數問題
問題 a 乙個簡單的整數問題 時間限制 5 sec 記憶體限制 128 mb 提交 75 解決 25 提交 狀態 討論版 命題人 quanxing edit testdata 題目描述 你有 n個整數,a1,a2,an。你需要處理兩種操作。一種操作是在給定間隔中為每個數字新增一些給定數字。另一種是要...
FAFU OJ 乙個簡單的問題
乙個簡單的問題 time limit 1000ms memory limit 65536kb total submissions 1386 accepted 240 share description 給定n個正整數和乙個正整數p,要求你從中找出兩個數字a,b使得a b p input 第一行兩個數...
乙個簡單的怪問題
乙個學員問了乙個關於io的怪問題,問題是這樣的 讀取鍵盤輸入的乙個字元,然後列印輸出這個字元,在列印字元的前面和後面分別加了乙個字串,程式的 如下 public class test 編譯並執行這個程式。1 輸入字元 a 命令列視窗列印輸出的結果如圖1所示,與我們預期的一樣。2 重新執行這個程式,直...