Problem - C1 - Codeforces (Unofficial mirror by Menci)
一个好区间中的所有子区间都是好的,使用双指针求出每段最大好区间。
const int MAX = 2e5 + 5;
int a[MAX];
void solve() {
int n;
int l = 1;
long long ans = 0;
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= n; ++i) { //i为右指针,l为左指针
while (a[i] < i - l + 1) ++l; //得到以i为终点的最大好区间
ans += (i - l + 1);
}
cout << ans << '\n';
}
Problem - B - Codeforces (Unofficial mirror by Menci)
要求重新构造的b数组满足a[i]=gcd(b[i],b[i+1]),易构造b[i]=lcm(a[i-1],a[i]),边界b[0]=a[0],b[n]=a[n-1],后遍历判断构造出的b数组是否满足条件。
int gcd(int a, int b) {
return !b ? a : gcd(b, a % b);
}
void solve() {
int n;
cin >> n;
int* a = new int[n + 1];
int* b = new int[n + 1];
for (int i = 0; i < n; i++)cin >> a[i];
b[0] = a[0], b[n] = a[n - 1]; //边界
for (int i = 1; i < n; i++) {
b[i] = a[i] / gcd(a[i], a[i - 1]) * a[i - 1]; //最小公倍数构造b
}
for (int i = 0; i < n; i++) { //判断b数组是否满足条件
if (a[i] != gcd(b[i], b[i + 1])) {
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
Fliptile - POJ 3279 - Virtual Judge
#define inf 0x3fffffff
int n, m;
int ma[20][20]; //输入数据
int maap[20][20]; //最优解
int teep[20][20]; //每一个位置的翻转次数
int dx[4] = { 0,0,-1,1 }; //四个方向
int dy[4] = { 1,-1,0,0 };
bool getcol(int x,int y) { //判断(x,y)的颜色,累加(x,y)本身颜色和四周的翻转次数
int temp = teep[x][y] + ma[x][y];
for (int i = 0; i < 4; i++) {
int x1 = x + dx[i];
int y1 = y + dy[i];
if (x1<1 || y1<1 || x1>n || y1>m)continue;
temp += teep[x1][y1];
}
return temp & 1; //相当于temp%2,若最终结果为奇,说明(x,y)最终颜色为1,下一行需要翻转
//否则不用
}
int dfs() {
for (int i = 2; i <= n; i++) { //从第2行开始
for (int j = 1; j <= m; j++) {
if (getcol(i - 1, j)) //求上一行的颜色,判断该行是否需要翻转
teep[i][j] = 1;
}
}
int temp = 0;
for (int i = 1; i <= m; i++) { //判断最后一行是否有黑色,如果有则完成不了
if (getcol(n, i))return inf;
}
for (int i = 1; i <= n; i++) { //累计总翻转次数
for (int j = 1; j <= m; j++) {
temp += teep[i][j];
}
}
return temp;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)cin >> ma[i][j];
int ans = inf;
for (int i = 0; i < (1 << m); i++) { //枚举第一行的所有翻转情况(采取二进制的枚举方式)
memset(teep, 0, sizeof(teep));
for (int j = 1; j <= m; j++) //给第一行赋值
teep[1][m - j + 1] = (i >> (j - 1)) & 1;
int cnt = dfs();
if (cnt < ans) { //保存最优解
ans = cnt;
memcpy(maap, teep, sizeof(teep));
}
}
if (ans == inf)cout << "IMPOSSIBLE\n";
else
for (int i = 1; i <= n; i++, cout << '\n')
for (int j = 1; j <= m; j++)cout << maap[i][j] << ' ';
return 0;
}
Pots - POJ 3414 - Virtual Judge
把A,B当前水量和当前操作数作为队列节点,进行bfs,求得最小操作数。
E - Pots ---bfs
int a, b, c; //A,B,C
typedef struct {
int x, y, t; //A,B当前水量,当前操作数
int setp[1005]; //每一步的操作类型
}node; //队列节点
char pt[7][20]={"","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
//6种操作
int vis[105][105]; //标记是否访问
int bfs() {
queue<node>q;
q.push(node{ 0,0,0 });
vis[0][0] = 1;
while (!q.empty()) {
node t = q.front();
q.pop();
if ((t.x == c) || (t.y == c)) { //终点
cout << t.t << '\n';
for (int i = 1; i <= t.t; i++) {
cout << pt[t.setp[i]] << '\n';
}
return 1;
}
for (int i = 1; i <= 6; i++) {
node t1 = t;
int k = t.x + t.y;
if (i == 1) { //A填满
t1.x = a;
}
else if (i == 2) { //B填满
t1.y = b;
}
else if (i == 3) { //A清空
t1.x = 0;
}
else if (i == 4) { //B清空
t1.y = 0;
}
else if (i == 5) { //A倒给B
if (k >= b) {
t1.y = b;
t1.x = k - b;
}
else {
t1.y = k;
t1.x = 0;
}
}
else { //B倒给A
if (k >= a) {
t1.x = a;
t1.y = k - a;
}
else {
t1.x = k;
t1.y = 0;
}
}
if (!vis[t1.x][t1.y]) {
vis[t1.x][t1.y] = 1;
t1.setp[++t1.t] = i; //记录每一步的操作类型
q.push(t1); //操作后的状态入队
}
}
}
return 0; //若始终没有水箱有C升水,返回0
}
int main() {
ios::sync_with_stdio(false);
cin >> a >> b >> c;
if (bfs() == 0)cout << "impossible\n";
return 0;
}