T1
a 是减去 k 的数组, b 是加 k 数组。此时两个数组已经是按照升序排序了,将 b 数组的元素依次填充
到 a 数组中,那么此时的极大值一定是max(a[tot -1],b[i]), 极小值一定是min(b[0],a[i+1]) ,还
有一种可能是本身。
/*
Date:
Source:
konwledge:
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
#include <algorithm>
#define orz cout << "AK IOI"
#define int long long
using namespace std;
const int maxn = 1e5 + 10;
inline int read()
{
int f = 0, x = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
return f ? -x : x;
}
inline void print(int X)
{
if(X < 0)
{
X = ~(X - 1);
putchar('-');
}
if(X > 9) print(X / 10);
putchar(X % 10 + '0');
}
int n, k, ans = 0x3f3f3f3f, a[maxn], tot, vis[maxn], b[maxn];
/*
void dfs(int now)
{
if(now == tot + 1)
{
for(int i = 1; i <= tot; i++) b[i] = a[i];
sort(a + 1, a + tot + 1);
ans = min(ans, a[tot] - a[1]);
for(int i = 1; i <= tot; i++) a[i] = b[i];
return ;
}
if(!vis[now])
{
a[now] += k;
vis[now] = 1;
}
dfs(now + 1);
a[now] -= k, vis[now] = 0;
a[now] -= k;
dfs(now + 1);
a[now] += k;
}
*/
signed main()
{
n = read(), k = read();
for(int i = 1; i <= n; i++) a[i] = read();
sort(a + 1, a + n + 1);
tot = unique(a + 1, a + n + 1) - a - 1;
for(int i = 1; i <= tot; i++)
{
a[i] -= k;
b[i] = a[i] + 2 * k;
}
ans = a[tot] - a[1];
for(int i = 1; i <= tot; i++)
ans = min(ans, max(b[i], a[tot]) - min(b[1], a[i + 1]));
printf("%lld", ans);
return 0;
}
/*
4 3
1 5 6 7
*/
T2
用 (f[i]) 记录上一个字符是否能被凑出来,用 vector 存这个字符后可以被拼出来的字符,然后 dfs 搜索输出。
字符串hash 的时候,一定要记得 s[i] - 'a' + 1
, 一定要 + 1啊!!!
/*
Date:2021.10.5
Source:模拟赛
knowledge:
*/
#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
#include <cstring>
#define orz cout << "AK IOI" << "
"
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define int long long
using namespace std;
const int maxn = 210;
const int mod = 1e9 + 7;
const int base = 13131;
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;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
}
int f[maxn], n, len1, ans[maxn], tot;
char s[maxn], ss[maxn];
map <int, bool> mp;
vector <int> e[maxn];
void dfs(int u, int tot)
{
ans[tot] = u;
if(u == len1)
{
for(int i = 1; i <= len1; i++)
{
cout << s[i];
if(i != len1)
for(int j = 1; j <= tot; j++) if(ans[j] == i) printf("_");
}
puts("");
return ;
}
for(int i = 0; i < e[u].size(); i++)
{
int v = e[u][i];
dfs(v, tot + 1);
}
}
signed main()
{
//freopen("ewfc.out","w",stdout);
scanf("%s", s + 1);
len1 = strlen(s + 1);
n = read();
for(int i = 1; i <= n; i++)
{
scanf("%s", ss + 1);
int res = 0, len = strlen(ss + 1);
for(int j = 1; j <= len; j++) res = (res * base % mod + ss[j] - 'a' + 1) % mod;
mp[res] = 1;
}
f[0] = 1;
for(int i = 1; i <= len1; i++)
{
for(int j = 1; j <= i; j++)
{
if(f[j - 1])
{
int res = 0;
for(int k = j; k <= i; k++) res = (res * base % mod + s[k] - 'a' + 1) % mod;
if(!mp[res]) continue;
f[i] = f[i] + f[j - 1];
e[j - 1].push_back(i);
}
}
}
if(f[len1] != 0) dfs(0, 1);
return 0;
}
T3
价格是一个波动的序列,所以根据贪心的策略,要在最高点卖,最低点买,这样的差是最大的,所以用
树状数组维护区间和,把一个区间里面那些最高点的和和最低点的相反数维护出来。
无情偷代码。
#include<bits/stdc++.h>
using namespace std;
int read()
{
int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
int n,m;
namespace PT1
{
const int N=100000+100;
int a[N],tree1[N],tree2[N],bz1[N],bz2[N],ma[N],nn;
int lowbit(int x)
{
return x&-x;
}
void update(int *tree,int pos,int c)
{
while(pos<=n)
{
tree[pos]+=c;
pos+=lowbit(pos);
}
}
int query(int *tree,int pos)
{
int ret=0;
while(pos)
{
ret+=tree[pos];
pos-=lowbit(pos);
}
return ret;
}
void updatep_v(int i)
{
if(i<=1||i>=n) return ;
int tmp=query(tree1,i)-query(tree1,i-1);
update(tree1,i,-tmp);
tmp=query(tree2,i)-query(tree2,i-1);
update(tree2,i,-tmp);
bz1[i]=0;
bz2[i]=0;
if(a[i]>a[i-1]&&a[i]>=a[i+1]) bz1[i]=1,update(tree1,i,a[i]);
if(a[i]<=a[i-1]&&a[i]<a[i+1]) bz1[i]=-1,update(tree1,i,-a[i]);
if(a[i]>=a[i-1]&&a[i]>a[i+1]) bz2[i]=1,update(tree2,i,a[i]);
if(a[i]<a[i-1]&&a[i]<=a[i+1]) bz2[i]=-1,update(tree2,i,-a[i]);
}
int main()
{
for(int i=1; i<=n; ++i) a[i]=read();
for(int i=2; i<n; ++i)
{
if(a[i]>a[i-1]&&a[i]>=a[i+1]) bz1[i]=1,update(tree1,i,a[i]);
if(a[i]<=a[i-1]&&a[i]<a[i+1]) bz1[i]=-1,update(tree1,i,-a[i]);
if(a[i]>=a[i-1]&&a[i]>a[i+1]) bz2[i]=1,update(tree2,i,a[i]);
if(a[i]<a[i-1]&&a[i]<=a[i+1]) bz2[i]=-1,update(tree2,i,-a[i]);
}
while(m--)
{
int opt=read();
if(opt==1)
{
int l=read(),r=read();
if(l==r)
{
cout<<0<<'
';
continue;
}
int ans=0;
if(l<r)
{
if(a[l]<a[l+1]) ans-=a[l];
if(a[r]>a[r-1]) ans+=a[r];
ans+=query(tree1,r-1)-query(tree1,l);
}
else
{
swap(l,r);
if(a[r]<a[r-1]) ans-=a[r];
if(a[l]>a[l+1]) ans+=a[l];
ans+=query(tree2,r-1)-query(tree2,l);
}
printf("%d
",ans);
}
else
{
int p=read(),w=read();
a[p]=w;
updatep_v(p-1),updatep_v(p),updatep_v(p+1);
}
}
return 0;
}
}
int main()
{
n=read(),m=read();
PT1::main();//100pts
return 0;
}