你的面前有n個數排成一行。分別為a1, a2, … , an。你打算在每相鄰的兩個 ai和 ai+1 間都插入乙個加號或者
減號或者乘號。那麼一共有 3^(n-1) 種可能的表示式。你對所有可能的表示式的值的和非常感興趣。但這畢竟太
簡單了,所以你還打算支援乙個修改操作,可以修改某個ai 的值。你能夠編寫乙個程式對每個修改都輸出修改完
之後所有可能表示式的和嗎?注意,修改是永久的,也就是說每次修改都是在上一次修改的基礎上進行, 而不是
在最初的表示式上進行。
第一行包含 2 個正整數 n 和 q,為數的個數和詢問的個數。
接下來一行 n 個非負整數,依次表示a1,a2...an
在接下來 q 行,其中第 ?? 行兩個非負整數ti 和vi,表示要將 ati 修改為 vi。其中 1 ≤ ti ≤ n。
保證對於 1 ≤ j ≤ n, 1 ≤ i≤ q,都有 aj,vi ≤ 10^4。
n,q<=100000,本題僅有三組資料
輸出共 q 行,其中第 i 行表示第 i 個詢問之後所有可能表示式的和,對10^9 + 7 取模。
題解首先想到+、-號會導致後面的所有結果相互抵消。所以對答案有貢獻的是前面一直是連乘的部分。即第乙個非乘號的前面部分
所以我們只需要維護字首積,修改的時候線段樹區間修改,先預處理逆元就可以做了
我認為這道題最關鍵的地方就是+、-號相互抵消,一下子簡化了問題。一開始想是否有規律,真實太蠢了
1 #include2 #include3 #include4 #include5using
namespace
std;
6#define maxn 100020
78 typedef long
long
ll;9
const ll mod = 1e9 + 7;10
struct
nodesgt[maxn * 4
];14
ll inv[maxn],fac[maxn],sum[maxn],pow[maxn];
15int
n,a[maxn],q,rt,tot;
1617 inline ll power(ll x,int
y)24
return res %mod;25}
26void
init()
31 inline void update(int
x)35
void build(int &x,int l,int
r)43
int mid = (l + r) >> 1;44
build(sgt[x].ls,l,mid);
45 build(sgt[x].rs,mid + 1
,r);
46update(x);47}
48 inline void mul(int
x,ll d)
52 inline void pushdown(int
x)58}59
void modify(int x,int l,int r,int ls,int
rs,ll d)
64pushdown(x);
65int mid = (l + r) >> 1;66
if ( ls <=mid ) modify(sgt[x].ls,l,mid,ls,rs,d);
67if ( rs > mid ) modify(sgt[x].rs,mid + 1
,r,ls,rs,d);
68update(x);69}
70int
main()
77 sum[0] = 1;78
for (int i = 1 ; i <= n ; i++) sum[i] = a[i] * sum[i - 1] %mod;
79 build(rt,1
,n);
80while ( q--)
88return0;
89 }
BZOJ 4597 Shoi2016 隨機序列
很可做的一道題 考慮一下一段序列的答案為b x,x為最右連續一段是乘積,然後和為x,b則為對應的左邊的和 然後考慮在右邊加乙個數k,分類討論一下發現x kx,b 2x 3b 於是就可以dp了 然後dp可以矩陣轉移 於是就可以用線段樹維護矩陣 就水過去了 好像很簡單哎,ac率好高的說 include ...
BZOJ4597 Shoi2016 隨機序列
bzoj4597 一開始看題一臉不可做的樣子。肯定又有什麼鬼畜的結論qa q 看看題解之後 和加減沒什麼關係。維護一下字首積的和就好了。qa q 然後自己拿n 3 手寫試了一發。md為什麼不自己想。an s i 1n 1 2 3n i 1 j 1i ai j 1 nai 線段樹維護一下就好了嘛。然後...
洛谷 P4597 序列sequence
此題的弱化版 和這個思路很相似 include define int long long using namespace std int n,x,ans priority queue int q 題解們都說 考慮當前的數x和之前的最大數y 預設x y已經滿足非降了 為了讓它非降,我們要做區間 x,y...