暴力水题 用map来标记一下就行
代码
#include
using namespace std;
const int N = 28;
map<char, int> mp;
void solve()
{
string str; cin >> str;
mp.clear();
for (int i = 0; i < 26; i ++ )
mp[str[i]] = i + 1;
int ans = 0;
string s; cin >> s;
for (int i = 1; i < s.size(); i ++ ) ans += abs(mp[s[i]] - mp[s[i - 1]]);
cout << ans << endl;
}
int main()
{
int t;
scanf("%d", &t);
while (t -- )
{
solve();
}
return 0;
}
找规律 每走四次就会返回起点 mod一下4走四步以内就可以找到答案
代码
#include
using namespace std;
typedef long long ll;
void solve()
{
ll x0, n;
scanf("%lld%lld", &x0, &n);
ll step = n % 4;
n -= step;
while (step)
{
n ++ ;
if (x0 & 1) x0 += n;
else x0 -= n;
step -- ;
}
cout << x0 << endl;
}
int main()
{
int t;
scanf("%d", &t);
while (t -- )
{
solve();
}
return 0;
}
第 i 轮减去最小数 等于 本来的数减去本来数组中第 i 小的数
拍一下序 求最大值即可
代码
#include
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n;
ll a[N];
void solve()
{
cin >> n;
for (int i = 1; i <= n; i ++ ) scanf("%lld", &a[i]);
sort(a + 1, a + 1 + n);
ll nmin;
for (int i = 1; i <= n; i ++ )
{
if (i == 1) nmin = a[i];
else nmin = max(nmin, a[i] - a[i - 1]);
}
cout << nmin << endl;
}
int main()
{
int t;
scanf("%d", &t);
while (t -- )
{
solve();
}
return 0;
}
把所有蓝色块子都移动到左边 红色块子都移动到右边 看看两边会出现重复吗 如果不出现就是yes 出现就no
代码
#include
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n;
int b[N], r[N], a[N];
bool st[N];
char s[N];
void solve()
{
int bcnt = 0, rcnt = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
scanf("%s", s + 1);
for (int i = 1; i <= n; i ++ )
if (s[i] == 'B') b[ ++ bcnt] = a[i];
else r[ ++ rcnt] = a[i];
sort(b + 1, b + bcnt + 1); sort(r + 1, r + rcnt + 1);
int tmp = 0;
for (int i = 1; i <= bcnt; i ++ )
{
if (b[i] >= i) tmp ++ ;
if (tmp != i) {puts("NO"); return;}
}
tmp = 0;
for (int i = rcnt; i >= 1; i -- )
{
if (r[i] <= i + bcnt) tmp ++ ;
if (tmp != (rcnt - i + 1)) {puts("NO"); return;}
}
puts("YES");
}
int main()
{
int t;
scanf("%d", &t);
while (t -- )
{
solve();
}
return 0;
}
维护一下x轴位置最小值和位置最大值 以及y轴位置最小值和位置最大值 当任意一个轴中出现区间大于n(m)时就break 当前两轴的xmin和ymin就是最佳位置的偏移量
代码
#include
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, m;
string s;
void solve()
{
scanf("%d%d", &n, &m); cin >> s;
int umin = 1, umax = 1, lmin = 1, lmax = 1;
int nowx = 1, nowy = 1;
for (int i = 0; i < s.size(); i ++ )
{
if (s[i] == 'L')
{
int tmp = nowx - 1;
if (tmp < lmin)
{
if (lmax - tmp + 1 > m) break;
lmin = tmp;
}
nowx = tmp;
}
else if (s[i] == 'R')
{
int tmp = nowx + 1;
if (tmp > lmax)
{
if (nowx - tmp + 1 > m) break;
lmax = tmp;
}
nowx = tmp;
}
else if (s[i] == 'U')
{
int tmp = nowy - 1;
if (tmp < umin)
{
if (umax - tmp + 1 > n) break;
umin = tmp;
}
nowy = tmp;
}
else if (s[i] == 'D')
{
int tmp = nowy + 1;
if (tmp > umax)
{
if (tmp - umin + 1 > n) break;
umax = tmp;
}
nowy = tmp;
}
}
cout << 2 - umin << ' ' << 2 - lmin << endl;
}
int main()
{
int t;
scanf("%d", &t);
while (t -- )
{
solve();
}
return 0;
}
对于每个块 我们都可以进行一次dfs 但是很明显这样可能会超时所以要剪枝 我们可以用len[i][j]来表示从(i, j)走最多走多少步 只遍历那些入度为0的点 最后再找一下是否有单环 因为单环所有点入度都不为0 用stack的话会爆空间
代码
#include
#define rep(i, n) for (int i = 1; i <= (n); i ++ )
using namespace std;
const int N = 2010;
inline int read()
{
register int x = 0, k = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') k = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x * k;
}
int n, m;
char c[N][N], s[N];
int len[N][N];
int ans, col, row;
void maintain(int len, int i, int j)
{
if (len > ans)
{
ans = len, row = i, col = j;
}
}
void getpos(int &x, int &y)
{
if (c[x][y] == 'L') y -- ;
else if (c[x][y] == 'R') y ++ ;
else if (c[x][y] == 'U') x -- ;
else if (c[x][y] == 'D') x ++ ;
}
bool valid(int x, int y)
{
if (x < 1 || x > n || y < 1 || y > m) return false;
return true;
}
void solve()
{
n = read(), m = read();
rep(i, n){
gets(s);
rep(j, m){
c[i][j] = s[j - 1];
len[i][j] = 0;
}
}
ans = 0;
rep(i, n)
rep(j, m){
if (len[i][j]) continue;
if (i != 1 && c[i - 1][j] == 'D') continue;
if (i != n && c[i + 1][j] == 'U') continue;
if (j != 1 && c[i][j - 1] == 'R') continue;
if (j != m && c[i][j + 1] == 'L') continue;
int x = i, y = j, nx, ny, cur = 0;
while (true)
{
++ cur, len[x][y] = -cur;
nx = x, ny = y;
getpos(nx, ny);
if (!valid(nx, ny) || len[nx][ny]) break;
x = nx, y = ny;
}
if (valid(nx, ny) && len[nx][ny] > 0)
cur += len[nx][ny];
maintain(cur, i, j);
x = i, y = j, ++ cur;
while (x != nx || y != ny)
{
len[x][y] += cur;
getpos(x, y);
}
if (!valid(nx, ny) || len[nx][ny] > 0) continue;
cur += len[nx][ny];
do{
len[x][y] = cur;
getpos(x, y);
} while(x != nx || y != ny);
}
rep(i, n)
rep(j, m){
if (len[i][j]) continue;
int cur = 0, x = i, y = j;
while (valid(x, y) && !len[x][y])
{
++ cur; len[x][y] = -1;
getpos(x, y);
}
maintain(cur, i, j);
}
printf("%d %d %d\n", row, col, ans);
}
int main()
{
int t;
t = read();
while (t -- )
{
solve();
}
return 0;
}
题意 : 给定两个数组 a 和 b 对于第 i 组 a和b总共要剪去m 问1-n 操作之后 ∣ ∑ a i − ∑ b i ∣ |\sum a_i - \sum b_i | ∣∑ai−∑bi∣的最小值为多少
∑ a i \sum a_i ∑ai 和 ∑ b i \sum b_i ∑bi 都是变值 很难求 我们可以将其中一个变成定值
即我们用 tot 表示 ∑ ( a i + b i − m ) \sum (a_i+b_i-m) ∑(ai+bi−m) 然后用 minsum 来表示所有b减去可能值后最小的值 maxsum表示所有b减去可能值之后的最大的值 则可以得到 tot - bsum * 2 = asum - bsum 即 ∣ ∑ a i − ∑ b i ∣ |\sum a_i - \sum b_i| ∣∑ai−∑bi∣ 则有这样几种情况
tot < minsum * 2 则b要尽量取小才能使值变小
tot > maxsum * 2 则b要尽量取大才能使值变大
minsum * 2 < tot < maxsum * 2 如果tot为奇 则结果为1 否则为 0
#include
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, m;
ll a[N], b[N];
void solve()
{
scanf("%d%d", &n, &m);
ll tot = 0, minsum = 0, maxsum = 0;
for (int i = 1; i <= n; i ++ )
{
scanf("%lld%lld", &a[i], &b[i]);
tot += (a[i] + b[i] - m);
minsum += b[i] >= m ? b[i] - m : 0;
maxsum += a[i] >= m ? b[i] : b[i] - (m - a[i]);
}
minsum *= 2, maxsum *= 2;
if (tot <= minsum)
{
printf("%lld\n", minsum - tot);
for (int i = 1; i <= n; i ++ )
if (b[i] >= m) { a[i] = 0; b[i] = m; }
else a[i] = m - b[i];
}
else if (tot >= maxsum)
{
printf("%lld\n", tot - maxsum);
for (int i = 1; i <= n; i ++ )
if (a[i] >= m) { a[i] = m; b[i] = 0; }
else b[i] = m - a[i];
}
else
{
if (tot & 1) puts("1");
else puts("0");
tot = (tot - minsum) / 2;
for (int i = 1; i <= n; i ++ )
{
ll maxsub = b[i] >= m ? m : b[i];
ll minsub = a[i] >= m ? 0 : m - a[i];
if (maxsub - tot >= minsub)
{
b[i] = maxsub - tot; a[i] = m - b[i];
tot = 0;
}
else
{
b[i] = minsub; a[i] = m - b[i];
tot -= maxsub - minsub;
}
}
}
for (int i = 1; i <= n; i ++ ) printf("%lld %lld\n", a[i], b[i]);
}
int main()
{
int t;
scanf("%d", &t);
while (t -- )
{
solve();
}
return 0;
}