你有乙個長度為 nn 的數列 \ ,這個數列由 0,10,1 組成,進行 mm 個的操作:
1~l~r1lr :把數列區間 [l, r][l,r] 內的所有數取反。即 00 變成 11 ,11 變成 00 。
2~l~r2lr :詢問數列在區間 [l, r][l,r] 內共有多少個本質不同的子串行。
輸入格式:
第一行包含兩個整數 n, mn,m ,意義如上所述。
接下來一行包含 nn 個數,表示數列 \ 。
接下來 mm 行,每行包含三個數,表示乙個操作,操作格式如上所述。
輸出格式:
對於每個詢問,輸出答案模 10^9 + 7109+7 的結果。
輸入樣例#1:
複製
4 4輸出樣例#1:1 0 1 0
2 1 4
2 2 4
1 2 3
2 1 4
複製
11對於 10 \%10% 的資料,1 \leq n, m \leq 10^21≤n,m≤102 。68
對於 30 \%30% 的資料,1 \leq n, m \leq 10^31≤n,m≤103 。
對於 100 \%100% 的資料,1 \leq n, m \leq 10^51≤n,m≤105 。
這道題同hdu6155(只不過我在hdu上t飛了)
首先我們考慮一下暴力怎麼寫
dp[i][1]表示到第$i$個位置,以$1$結尾,本質不同的子串行
dp[i][0]表示到第$i$個位置,以$0$結尾,本質不同的子串行
轉移的時候,假設第$i$個字元是1
那麼對它有貢獻的是以前以$0$結尾的子串行,以及以前以$1$結尾的子串行,以及空串
那麼此時
$dp[i][1]=dp[i-1][0]+dp[i-1][1]+1$
$dp[i][0]=dp[i-1][0]$
當第$i$個字元是$0$的時候同理,不難得到
$dp[i][1]=dp[i-1][1]$
$dp[i][0]=dp[i-1][0]+dp[i-1][1]+1$
大家有沒有發現一件事情?
這個dp的轉移是遞推!也就是說我們可以用矩陣乘法來加速!
而矩陣乘法可以用線段樹來維護!
它的矩陣為
對於操作1的話,先交換要改變的矩陣的第一行和第二行,再交換要改變的矩陣的第一列和第二列
至於為什麼?這個可以轉移之間的關係入手,也可以直接找規律
這樣就實現了兩個矩陣的轉換
另外還有一點、
對於結果矩陣,我們只會用到[3][1]和[3][2]這兩項(分別代表dp[n][1],dp[n][0])
//luogu-judger-enable-o2
//luogu-judger-enable-o2
#include#include
#include
#define ll long long int
#define ls k<<1
#define rs k<<1|1
using
namespace
std;
const
int maxn=1e6+10
;const
int mod=1e9+7
;inline
intread()
while(c>='
0'&&c<='9')
return x*f;
}char
c[maxn];
struct
matrix
};struct
node
t[maxn];
matrix zero,one,hhhhh;
matrix rev(matrix &a)
matrix matrixmul(matrix a,matrix b)
void update(int
k)void pushdown(intk)}
void build(int k,int ll,int
rr)
int mid=ll+rr>>1
; build(ls,ll,mid);
build(rs,mid+1
,rr);
update(k);
}void intervalchange(int k,int ll,int
rr) pushdown(k);
int mid=t[k].l+t[k].r>>1
;
if(ll<=mid) intervalchange(ls,ll,rr);
if(rr>mid) intervalchange(rs,ll,rr);
update(k);
}matrix intervalask(
int k,int ll,int
rr) pushdown(k);
ll mid=t[k].l+t[k].r>>1
;
if(ll<=mid)
ans=matrixmul(intervalask(ls,ll,rr),ans);
if(rr>mid)
ans=matrixmul(ans,intervalask(rs,ll,rr));
return
ans;
}int
main()
else
if(opt==2
)
}
}return0;
}
洛谷T21776 子串行
你有乙個長度為 nn 的數列 這個數列由 0,10,1 組成,進行 mm 個的操作 1 l r1lr 把數列區間 l,r l,r 內的所有數取反。即 00 變成 11 11 變成 00 2 l r2lr 詢問數列在區間 l,r l,r 內共有多少個本質不同的子串行。輸入格式 第一行包含兩個整數 n,...
洛谷 P1410 子串行
這題乍一看毫無思路。顯然不可能窮舉長度為n 2的嚴格遞增子串行。不過聯想到noip1999 普及組 的飛彈攔截的第二問,就有思路了。這題其實與它的第二問差不多,只要算出該序列的最大非公升子串行長度l,判斷一下是否大於2即可。1.假如l 2,顯然乙個嚴格遞增子串行至多包含非公升子串行的乙個元素,2個子...
洛谷 P1410 子串行
給定乙個長度為n n為偶數 的序列,問能否將其劃分為兩個長度為n 2的嚴格遞增子串行,輸入格式 若干行,每行表示一組資料。對於每組資料,首先輸入乙個整數n,表示序列的長度。之後n個整數表示這個序列。輸出格式 同輸入行數。對於每組資料,如果存在一種劃分,則輸出 yes 否則輸出 no 輸入樣例 1 6...