## 题解

### $$T1$$ K 子琪

for(int i = 0; i ^ n; i++)
for(int j = 0; j ^ m; j++)
if(!i || !j) _g[i][j] = i | j;
else _g[i][j] = i > j ? _g[i - j][j] : _g[i][j - i];


for(int i = 1; i ^ n + 1; i++) fac[i] = fac[i - 1] * i % mod;
inv[n] = power(fac[n], mod - 2);
for(int i = n; i; i--) inv[i - 1] = inv[i] * i % mod;


/*
Source: K子棋
思路很精妙 坐标减一 除以gcd统计一条直线上点的个数
gcd 通过递推求出 预处理阶乘以及逆元算组合数
特判 k = 1
*/
#include<cstdio>
#include<cstring>
#include<map>
#define pt putchar(' ')
#define pn putchar('\n')
#define int long long
#define Max(x, y) ((x) > (y) ? (x) : (y))
/*-----------------------------------------------------------------------*/
const int B = 5e3 + 7;
const int mod = 998244353;
const int INF = 0x3f3f3f3f;
/*-----------------------------------------------------------------------*/
void File() {
freopen("connectk.in", "r", stdin);
freopen("connectk.out", "w", stdout);
}
/*-----------------------------------------------------------------------*/
int n, m, K, A, a, b, p, l, fac[B], inv[B], ans, kcnt, _g[B][B], mp[B][B];
/*-----------------------------------------------------------------------*/
inline int read() {
int x = 0, f = 0; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = 1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return f ? -x : x;
}
void print(int x) {if(x > 9) print(x / 10); putchar(x % 10 ^ 48);}
void Print(int x) {if(x < 0) putchar('-'), x = -x; print(x);}
/*-----------------------------------------------------------------------*/
int power(int _a, int _b) {int res = 1; for(; _b; _a = _a * _a % mod, _b >>= 1) if(_b & 1) res = res * _a % mod; return res;}
void print_mp() {
for(int i = 0; i ^ n; i++) {for(int j = 0; j ^ m; j++) Print(mp[i][j]), pt; pn;}
}
int C(int n, int m) {if(!n || !m || n == m) return 1; return fac[n] * inv[m] % mod * inv[n - m] % mod;}
/*-----------------------------------------------------------------------*/
signed main() {
File();
n = read(); m = read(); K = read(); A = read(); a = read(); b = read(); p = read(); l = read();
fac[0] = 1; a %= p; A %= p; b %= p;
for(int i = 0; i ^ n; i++) for(int j = 0; j ^ m; j++) a = (A * a % p + b) % p, mp[i][j] = a <= l;
if(K == 1) {
kcnt = 0;
for(int i = 0; i ^ n; i++) for(int j = 0; j ^ m; j++) kcnt = (kcnt + mp[i][j]) % mod;
Print(kcnt); return 0;
}
for(int i = 1; i ^ Max(n, m) + 1; i++) fac[i] = fac[i - 1] * i % mod, inv[i] = power(fac[i], mod - 2);
for(int i = 0; i ^ n; i++) for(int j = 0; j ^ m; j++) if(!i || !j) _g[i][j] = i | j; else _g[i][j] = i > j ? _g[i - j][j] : _g[i][j - i];
for(int i = n - 1, g; ~i; i--) for(int j = m - 1; ~j; j--) if((i || j) && _g[i][j] != 1) g = _g[i][j], mp[i / g][j / g] += mp[i][j], mp[i][j] = 0;
for(int i = 0; i ^ n; i++) for(int j = 0; j ^ m; j++) if(_g[i][j] == 1 && mp[0][0] + mp[i][j] >= K) ans = (ans + C(mp[0][0] + mp[i][j], K)) % mod;
Print(ans);
return 0;
}


### $$T3$$ 能源供应

1. 如果火炉开着

哪怕不用 同样需要有 $$D$$ 的代价 所以不用白不用

1. $$K \geq v_i$$

我们尽量少的使用火炉 但是还是要充分利用 $$D$$ 的花费

$\lfloor \frac DK \rfloor \times K + v_i \times \left(a_i - \lfloor \frac DK \rfloor \right) \\ \left(\lfloor \frac DK \rfloor + 1\right) \times K + v_i \times \left( a_i - \lfloor \frac DK \rfloor - 1\right)$

对这两个东西取较小的

当然要满足后面那一项是正的

2. $$K < v_i$$

只用火炉

$\max(D, Ka_i)$

其实根本不用分类讨论的

直接对于这三个式子取最小值即可 记为 $$c_i$$

2. 如果火炉没开

只能使用风力发电

$v_ia_i$

记为 $$d_i$$

$f_{i, 0} = \min \left(f_{i - 1, 0} + d_i, f_{i - 1, 1} + d_i \right)\\ f_{i, 1} = \min \left(f_{i - 1, 0} + C + c_i, f_{i - 1, 1} + c_i \right)\\$

/*
Source: 能源供应
*/
#include<cstdio>
#include<cstring>
#define pt putchar(' ')
#define pn putchar('\n')
#define int long long
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
/*----------------------------------------------------------*/
const int B = 2e5 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f3f3f3f3f;
/*----------------------------------------------------------*/
inline void File() {
freopen("energy.in", "r", stdin);
freopen("energy.out", "w", stdout);
}
/*----------------------------------------------------------*/
int n, C, D, K, v[B], a[B], q, c[B], d[B], f[B][2];
/*----------------------------------------------------------*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void print(int x) {if(x > 9) print(x / 10); putchar(x % 10 ^ 48);}
void Print(int x) {if(x < 0) putchar('-'), x = -x; print(x);}
/*----------------------------------------------------------*/
void work() {
memset(f, 0, sizeof f); f[0][1] = C;
for(int i = 1; i ^ n + 1; i++)
f[i][0] += Min(f[i - 1][0] + d[i], f[i - 1][1] + d[i]), f[i][1] = Min(f[i - 1][0] + C + c[i], f[i - 1][1] + c[i]);
Print(Min(f[n][0], f[n][1])); pn;
}
/*----------------------------------------------------------*/
signed main() {
File();
n = read(); C = read(); D = read(); K = read();
for(int i = 1; i ^ n + 1; i++) v[i] = read();
for(int i = 1; i ^ n + 1; i++) a[i] = read();
for(int i = 1; i ^ n + 1; i++)
{
int tmp1 = INF, tmp2 = INF;
if(D / K <= a[i]) tmp1 = Max(D, D / K * K) + v[i] * (a[i] - D / K);
if(D / K + 1 <= a[i]) tmp2 = Max(D, (D / K + 1) * K) + v[i] * (a[i] - D / K - 1);
c[i] = Min(Max(D, K * a[i]), Min(tmp1, tmp2)); d[i] = v[i] * a[i];
}
q = read();
while(q--)
{
int x = read(), y = read(); v[x] = y;
int tmp1 = INF, tmp2 = INF;
if(D / K <= a[x]) tmp1 = Max(D, D / K * K) + v[x] * (a[x] - D / K);
if(D / K + 1 <= a[x]) tmp2 = Max(D, (D / K + 1) * K) + v[x] * (a[x] - D / K - 1);
c[x] = Min(Max(D, K * a[x]), Min(tmp1, tmp2)); d[x] = v[x] * a[x];
work();
}
return 0;
}
/*
5 8 1 4
6 7 2 2 7
7 5 8 5 2

*/


$\begin{Vmatrix} f_{i - 1, 0} & f_{i - 1, 1} \end{Vmatrix} \bigotimes \begin{Vmatrix} d_i & C + c_i \\ d_i & c_i \end{Vmatrix} \\= \begin{Vmatrix} \min(f_{i - 1, 0} + d_i, f_{i - 1, 1} + d_i) & \min(f_{i - 1, 0 + C + c_i}, f_{i - 1, 1} + c_i) \end{Vmatrix} \\= \begin{Vmatrix} f_{i, 0} & f_{i, 1} \end{Vmatrix}$

/*
Source: 能源供应
对于每一天来说 当是否开火确定以后 这一天的最优花费是固定的
通过 dp 枚举火机的状态 直接转移
注意数据比较大 极大值要取的足够大
需要线段树维护广义矩阵乘进行优化
*/
#include<cstdio>
#include<cstring>
#define pt putchar(' ')
#define pn putchar('\n')
#define int long long
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
/*----------------------------------------------------------*/
const int B = 2e5 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f3f3f3f3f;
/*----------------------------------------------------------*/
inline void File() {
freopen("energy.in", "r", stdin);
freopen("energy.out", "w", stdout);
}
/*----------------------------------------------------------*/
int n, C, D, K, v[B], a[B], q, c[B], d[B], f[B][2];
/*----------------------------------------------------------*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void print(int x) {if(x > 9) print(x / 10); putchar(x % 10 ^ 48);}
void Print(int x) {if(x < 0) putchar('-'), x = -x; print(x);}
/*----------------------------------------------------------*/
//void work() {
//	memset(f, 0, sizeof f); f[0][1] = C;
//	for(int i = 1; i ^ n + 1; i++)
//		f[i][0] += Min(f[i - 1][0] + d[i], f[i - 1][1] + d[i]), f[i][1] = Min(f[i - 1][0] + C + c[i], f[i - 1][1] + c[i]);
//	Print(Min(f[n][0], f[n][1])); pn;
//}
namespace Seg {
#define ls(x) x << 1
#define rs(x) x << 1 | 1
#define mid (t[p].l + t[p].r >> 1)
struct M {
int a[3][3];
//		M() {memset(a, 63, sizeof a);}
void RE(int i) {a[0][0] = d[i]; a[0][1] = C + c[i]; a[1][0] = d[i]; a[1][1] = c[i];}
};
struct node {int l, r; M sum;} t[B << 2];
M operator * (M x, M y) {
M z;
z.a[0][0] = Min(x.a[0][0] + y.a[0][0], x.a[0][1] + y.a[1][0]);
z.a[0][1] = Min(x.a[0][0] + y.a[0][1], x.a[0][1] + y.a[1][1]);
z.a[1][0] = Min(x.a[1][0] + y.a[0][0], x.a[1][1] + y.a[1][0]);
z.a[1][1] = Min(x.a[1][0] + y.a[0][1], x.a[1][1] + y.a[1][1]);
//		for(int i = 0; i ^ 3; i++)
//			for(int k = 0; k ^ 3; k++)
//				for(int j = 0; j ^ 3; j++)
//					z.a[i][j] = Min(z.a[i][j], x.a[i][k] + y.a[k][j]);
return z;
}
node operator + (node x, node y) {
node z; z.l = x.l; z.r = y.r;
z.sum = x.sum * y.sum;
return z;
}
void build(int p, int l, int r) {
t[p].l = l; t[p].r = r; if(l == r) {t[p].sum.RE(l); return ;}
build(ls(p), l, mid); build(rs(p), mid + 1, r); t[p] = t[ls(p)] + t[rs(p)];
}
void up_date(int p, int pos) {
if(t[p].l == pos && pos == t[p].r) {t[p].sum.RE(pos); return ;}
if(pos <= mid) up_date(ls(p), pos); else up_date(rs(p), pos); t[p] = t[ls(p)] + t[rs(p)];
}
}
/*----------------------------------------------------------*/
signed main() {
File();
n = read(); C = read(); D = read(); K = read();
for(int i = 1; i ^ n + 1; i++) v[i] = read();
for(int i = 1; i ^ n + 1; i++) a[i] = read();
for(int i = 1; i ^ n + 1; i++)
{
int tmp1 = INF, tmp2 = INF;
if(D / K <= a[i]) tmp1 = Max(D, D / K * K) + v[i] * (a[i] - D / K);
if(D / K + 1 <= a[i]) tmp2 = Max(D, (D / K + 1) * K) + v[i] * (a[i] - D / K - 1);
c[i] = Min(Max(D, K * a[i]), Min(tmp1, tmp2)); d[i] = v[i] * a[i];
}
Seg::build(1, 1, n);
q = read();
while(q--)
{
int x = read(), y = read(); v[x] = y;
int tmp1 = INF, tmp2 = INF;
if(D / K <= a[x]) tmp1 = Max(D, D / K * K) + v[x] * (a[x] - D / K);
if(D / K + 1 <= a[x]) tmp2 = Max(D, (D / K + 1) * K) + v[x] * (a[x] - D / K - 1);
c[x] = Min(Max(D, K * a[x]), Min(tmp1, tmp2)); d[x] = v[x] * a[x];
//		work();
Seg::up_date(1, x); Print(Min(Seg::t[1].sum.a[0][0], Seg::t[1].sum.a[0][1])); pn;
}
return 0;
}
/*
5 8 1 4
6 7 2 2 7
7 5 8 5 2

*/


### $$T4$$ 小 K 的数列

$$a$$ 单调递增 所有的 $$b$$ 均为 $$1$$ 使 $$V = 10^{18}$$ 每次修改 $$1$$ 号点 每次加一

/*
Source: 小K的数列
对区间 [l, r] 若有 l > 1 且 a[l - 1] < max(l, r) 那么考虑区间 [l - 1, r] 一定优于 [l, r]
所以只需要考虑两边的数都比区间中的最大值大的区间 即 使每个值作为其所在区间的最大值的最大区间
这样的区间一共有 n 个 以较大值为树根构建笛卡尔树之后 一个区间对应的就是该树上的一点为根的子树
对于每一次询问向上暴力修改 找到的第一个位置一定是最小的
*/
#include<cstdio>
#include<cstring>
#define pt putchar(' ')
#define pn putchar('\n')
#define ll long long
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))
/*----------------------------------------------------------*/
const int B = 3e5 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*----------------------------------------------------------*/
inline void File() {
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
}
/*----------------------------------------------------------*/
int n, a[B], b[B], q, max, ans = INF;
ll V;
/*----------------------------------------------------------*/
inline ll read() {
ll x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void Print(ll x) {if(x < 0) putchar('-'), x = -x; if(x > 9) Print(x / 10); putchar(x % 10 ^ 48);}
/*----------------------------------------------------------*/
namespace CT {
#define ls(x) t[x].l
#define rs(x) t[x].r
#define fa(x) t[x].fa
struct node {int l, r, fa; ll sum; bool flag;} t[B];
int rt, st[B], top;
void build() {
for(int i = 1; i ^ n + 1; i++)
{
int k = top;
while(k && a[st[k]] < a[i]) k--;
if(k) rs(st[k]) = i, fa(i) = st[k]; if(k < top) ls(i) = st[k + 1], fa(st[k + 1]) = i;
st[++k] = i; top = k;
}
}
void dfs0(int p) {
if(ls(p)) dfs0(ls(p)); if(rs(p)) dfs0(rs(p));
t[p].sum = t[ls(p)].sum + t[rs(p)].sum + 1ll * b[p];
if(t[p].sum >= V) {t[p].flag = 1; ans = Min(ans, a[p]);}
}
void up_date(int p, int k) {
if(t[p].flag || !p) return ;
t[p].sum += k; if(t[p].sum >= V) {t[p].flag = 1; ans = Min(ans, a[p]);}
up_date(fa(p), k);
}
}
/*----------------------------------------------------------*/
int main() {
n = read(); V = read();
for(int i = 1; i ^ n + 1; i++) {a[i] = read(); if(a[i] > max) max = a[i], CT::rt = i;}
for(int i = 1; i ^ n + 1; i++) b[i] = read();
CT::build(); CT::dfs0(CT::rt);
q = read();
while(q--)
{
int x = read(), y = read();
CT::up_date(x, y);
Print(ans == INF ? -1 : ans); pn;
}
return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int MAXN = 300005;

int n,q,ans,top;
int S[MAXN];
int a[MAXN];
int b[MAXN];
int l[MAXN];
int r[MAXN];
int pos[MAXN];
int fa[MAXN][20];

bool vis[MAXN];

ll V;
ll sum[MAXN];

void modify(int p,int x)
{
while (p <= n)
{
sum[p] += x;
p += p & -p;
}
}

ll query(int p)
{
ll res = 0;
while (p >= 1)
{
res += sum[p];
p -= p & -p;
}
return res;
}

int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
scanf("%d%lld",&n,&V);
for (int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
pos[a[i]] = i;
}
for (int i = 1;i <= n;i++)
{
scanf("%d",&b[i]);
modify(i,b[i]);
if (b[i] < 0 || b[i] > 1e9)
return 0;
}
a[0] = a[n + 1] = 1e9;
S[++top] = 0;
for (int i = 1;i <= n;i++)
{
while (a[S[top]] < a[i])
top--;
l[i] = S[top];
S[++top] = i;
}
S[top = 1] = n + 1;
for (int i = n;i >= 1;i--)
{
while (a[S[top]] < a[i])
top--;
r[i] = S[top];
S[++top] = i;
}
for (int i = 1;i <= n;i++)
{
fa[i][0] = (a[l[i]] < a[r[i]] ? l[i] : r[i]);
if (a[i] == n)
fa[i][0] = 0;
}
for (int i = n;i >= 1;i--)
{
int u = pos[i];
for (int j = 1;j <= 18;j++)
fa[u][j] = fa[fa[u][j - 1]][j - 1];
}
ans = 1e9;
for (int i = 1;i <= n;i++)
if (query(r[i] - 1) - query(l[i]) >= V)
{
vis[i] = 1;
ans = min(ans,a[i]);
}
scanf("%d",&q);
while (q--)
{
int x,y;
scanf("%d%d",&x,&y);
modify(x,y);
int u;
if (!vis[x])
{
do
{
u = x;
for (int j = 18;j >= 0;j--)
if (fa[u][j] && !vis[fa[u][j]])
u = fa[u][j];
if (query(r[u] - 1) - query(l[u]) >= V)
{
vis[u] = 1;
ans = min(ans,a[u]);
}
}while (u != x && vis[u]);
}
printf("%d\n",ans == 1e9 ? -1 : ans);
}
return 0;
}