Dashboard - Codeforces Round 895 (Div. 3) - Codeforces
问多少次能使a 和 b相等,就是abs(a - b) / 2除c向上取整,也就是abs(a - b)除2c向上取整。
#include
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair PII;
typedef long long ll;
void solve()
{
int a, b, c;
cin >> a >> b >> c;
a = abs(a - b), c *= 2;
cout << (a + c - 1) / c << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
真是一篇好阅读理解,读了好久
就是说陷阱会在踩到后经过s秒触发,触发后不能通过,最少往前走d + s / 2(向上取整)格子后就回不来了,把所有的d + s / 2比较取最小值然后减一就是答案。
#include
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair PII;
typedef long long ll;
void solve()
{
int n;
cin >> n;
int ans = 2e9;
for(int i = 0; i < n; i ++)
{
int a, b;
cin >> a >> b;
a = a + (b + 1) / 2;
ans = min(ans, a);
}
cout << ans - 1 << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
如果是>2的偶数的话,x - 2和x就是一组解
如果l == r且l是奇数的话,可以求l的因子,设因子为d,x - d 和 d 都可以被d整除,这样也可以求出一组解
之后注意一些边界条件就好了。
#include
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair PII;
typedef long long ll;
void solve()
{
int l, r;
cin >> l >> r;
if(r < 4)
{
cout << -1 << endl;
return;
}
if(r % 2 && l == r)
{
for(int i = 2; i * i <= l; i ++)
{
if(l % i == 0)
{
cout << l - i << ' ' << i << endl;
return;
}
}
cout << -1 << endl;
return;
}
if(r % 2)
{
cout << r - 3 << ' ' << 2 << endl;
}
else cout << r - 2 << ' ' << 2 << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
贪心。
设lcm为x和y的最大公倍数,lcm的倍数的位置有重合,先加后减等于零,在这里操作是没意义的。
加操作有意义的点的数量:n / x - n / lcm
减操作有意义的点的数量:n / y - n / lcm
加的话从n开始加,依次递减n-1、n-2这样
减的话从1开始加,依次递增2、3这样。
#include
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair PII;
typedef long long ll;
void solve()
{
ll n, x, y;
cin >> n >> x >> y;
ll gcd = __gcd(x, y);
ll lcm = x * y / gcd;
ll a = n / x - n / lcm, b = n / y - n / lcm;
a = a * (2 * n - a + 1) / 2;
b = b * (b + 1) / 2;
cout << a - b << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
前缀和。
做出这道题需要了解的两个性质:
1. x ^ x = 0;
2. 0 ^ x = x;
根据这两条性质我们就可以求出任意一段连续区间的异或和,使用前缀数组实现,用b[]表示
b[n]表示从第一项异或到第n项
b[r] ^ b[l - 1]就等于 b[l - 1] ^ b[l] ^ ... ^ b[r] ^ b[l - 1] = b[l] ^ ... ^ b[r];
对于第一个操作,区间修改,如果一个数x的对应位置上的树为1,被修改后变成0,就相当于x没被启用,变成0了,就相当于异或x本身,
如果一个数x的对应位置上的树为0,被修改后变成1,就相当于x被启用了,变成了1,也相当于异或x本身。
先用一个ans计算出被启用的数的异或和,之后每进行一次区间修改就相当于异或一遍这个区间内的异或和,非常的easy。
然后第二个操作,如果是查1,直接输出ans就好了
如果是查2,输出前n项异或前缀和异或ans就好了
听说有人线段树过了,挺nb的,之后再学一学。
#include
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair PII;
typedef long long ll;
const int N = 100010;
int a[N], b[N];
void solve()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
{
cin >> a[i];
b[i] = b[i - 1] ^ a[i];
}
string s;
cin >> s;
s = ' ' + s;
int ans = 0;
for(int i = 1; i <= n; i ++)
{
if(s[i] == '1')
{
ans ^= a[i];
}
}
int Q;
cin >> Q;
while(Q --)
{
int op;
cin >> op;
if(op == 1)
{
int l, r;
cin >> l >> r;
int res = b[r] ^ b[l - 1];
ans ^= res;
}
else
{
int x;
cin >> x;
if(x == 1)cout << ans << ' ';
else cout << (b[n] ^ ans) << ' ';
}
}
cout << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
赛后学的线段树做法:
#include
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair PII;
typedef long long ll;
const int N = 100010;
int n;
int a[N];
string s;
struct Node
{
int l, r;
int sum0, sum1;
int f;
}tr[N * 4];
void pushup(int u)
{
tr[u].sum0 = tr[u << 1].sum0 ^ tr[u << 1 | 1].sum0;
tr[u].sum1 = tr[u << 1].sum1 ^ tr[u << 1 | 1].sum1;
}
void pushdown(int u)
{
Node &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
if(tr[u].f)
{
swap(left.sum0, left.sum1);
swap(right.sum0, right.sum1);
left.f ^= tr[u].f;
right.f ^= tr[u].f;
tr[u].f = 0;
}
}
void build(int u, int l, int r)
{
if(l == r)
{
if(s[l] == '0')tr[u] = {l, r, a[l], 0, 0};
else tr[u] = {l, r, 0, a[l], 0};
}
else
{
tr[u] = {l, r, 0, 0, 0};
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int l, int r)
{
if(tr[u].l >= l && tr[u].r <= r)
{
swap(tr[u].sum0, tr[u].sum1);
tr[u].f ^= 1;
}
else
{
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid)modify(u << 1, l, r);
if(r > mid)modify(u << 1 | 1, l, r);
pushup(u);
}
}
void solve()
{
cin >> n;
for(int i = 1; i <= n; i ++)cin >> a[i];
cin >> s;
s = ' ' + s;
build(1, 1, n);
int Q;
cin >> Q;
while(Q --)
{
int op;
cin >> op;
if(op == 1)
{
int l, r;
cin >> l >> r;
modify(1, l, r);
}
else
{
int x;
cin >> x;
if(x == 0)cout << tr[1].sum0 << ' ';
else cout << tr[1].sum1 << ' ';
}
}
cout << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
Node节点存两个值sum0和sum1,f作为懒标记。
i在要a[i]之前被卖出,其实就是拓扑排序,先输出没在环中的点,然后每个环中,值最小的那个点最后卖出一定是最优的,类似贪心。
其实我在想如果一个点同时出现在两个环中该怎么办,然后发现这种情况其实不存在
比如
如果一个点出现在多个环中,边数会比点数还多,因为又要求每个点的出度都为1,所以这种情况显然是与输入要求矛盾的,所以一个点一定最多出现在一个环内,证毕。
#include
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair PII;
typedef long long ll;
const int N = 100010;
int n;
int h[N], e[N], ne[N], idx;
int d[N];
int a[N], b[N];
bool st[N];
vector ans;
queue q;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void bfs()
{
while(q.size())
{
int t = q.front();
q.pop();
ans.push_back(t);
for(int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if(st[j])continue;
d[j] --;
if(!d[j])
{
q.push(j);
st[j] = true;
}
}
}
}
void solve()
{
idx = 0;
ans.clear();
cin >> n;
priority_queue, greater> heap;
for(int i = 1; i <= n; i ++)d[i] = 0;
for(int i = 1; i <= n; i ++)
{
st[i] = false;
h[i] = -1;
cin >> a[i];
add(i, a[i]);
d[a[i]] ++;
}
for(int i = 1; i <= n; i ++)
{
cin >> b[i];
heap.push({b[i], i});
if(!d[i])
{
st[i] = true;
q.push(i);
}
}
bfs();
while(ans.size() < n)
{
int ver;
while(heap.size())
{
PII t = heap.top();
heap.pop();
if(!st[t.second])
{
ver = t.second;
break;
}
}
st[ver] = true;
for(int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if(st[j])continue;
d[j] --;
if(!d[j])
{
q.push(j);
st[j] = true;
}
}
bfs();
ans.push_back(ver);
}
for(int i = 0; i < n; i ++)cout << ans[i] << ' ';
cout << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}