Codeforces Round 971 (Div. 4)题解记录(G3待补)
A. Minimize!
暴力模拟一遍即可
#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
ll ksm(ll x, ll y) { ll ans = 1; while (y) { if (y & 1)ans = (ans % mod * (x % mod)) % mod; x = (x % mod) * (x % mod) % mod % mod; y >>= 1; }return ans % mod % mod; }
ll gcd(ll x, ll y) { if (y == 0)return x; else return gcd(y, x % y); }
void fio() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); }
int main()
{
ll t;
cin>>t;
while(t--)
{
ll a,b;
cin>>a>>b;
ll zm=1561616154;
for(ll i=a;i<=b;i++)
{
zm=min(zm,i-a+b-i);
}
cout<<zm<<endl;
}
}
B. osu!mania
暴力模拟
#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
ll ksm(ll x, ll y) { ll ans = 1; while (y) { if (y & 1)ans = (ans % mod * (x % mod)) % mod; x = (x % mod) * (x % mod) % mod % mod; y >>= 1; }return ans % mod % mod; }
ll gcd(ll x, ll y) { if (y == 0)return x; else return gcd(y, x % y); }
void fio() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); }
int main()
{
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
vector<ll>g;
string f[600];
for(ll i=1;i<=n;i++)
{
cin>>f[i];
}
for(ll i=n;i>=1;i--)
{
for(ll j=0;j<=3;j++)
{
if(f[i][j]=='#')
{
g.push_back(j+1);
break;
}
}
}
for(auto j:g)
{
cout<<j<<" ";
}
cout<<endl;
}
}
C. The Legend of Freya the Frog
最大值其实取决于你什么方向最晚到目标位置
如果是水平方向更大直接两倍减一
如果是竖直方向直接两倍即可
#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
ll ksm(ll x, ll y) { ll ans = 1; while (y) { if (y & 1)ans = (ans % mod * (x % mod)) % mod; x = (x % mod) * (x % mod) % mod % mod; y >>= 1; }return ans % mod % mod; }
ll gcd(ll x, ll y) { if (y == 0)return x; else return gcd(y, x % y); }
void fio() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); }
int main()
{
ll t;
cin>>t;
while(t--)
{
ll x,y,k;
cin>>x>>y>>k;
ll ans=x/k+(x%k>0);
ll cnt=y/k+(y%k>0);
if(cnt<ans)
{
cout<<ans+ans-1<<endl;
}
else
{
cout<<cnt+cnt<<endl;
}
}
}
D. Satyam and Counting
当直角三角形的直角边不垂直水平方向,直接特判计数
否则直接考虑除了上下两个点的组合数情况
#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
ll ksm(ll x, ll y) { ll ans = 1; while (y) { if (y & 1)ans = (ans % mod * (x % mod)) % mod; x = (x % mod) * (x % mod) % mod % mod; y >>= 1; }return ans % mod % mod; }
ll gcd(ll x, ll y) { if (y == 0)return x; else return gcd(y, x % y); }
void fio() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); }
map<pair<ll,ll>,ll>q;
int main()
{
ll t;
cin>>t;
while(t--)
{
q.clear();
ll n;
cin>>n;
ll ans=0;
for(ll i=1;i<=n;i++)
{
ll x,y;
cin>>x>>y;
q[{x,y}]++;
if(y==0)
{
if(q[{x,1}]>0)
ans+=n-2;
}
else
{
if(q[{x,0}]>0)
ans+=n-2;
}
if(y==0)
{
if(q[{x-1,1}]&&q[{x+1,1}])
ans++;
if(q[{x-1,1}]&&q[{x-2,0}])
ans++;
if(q[{x+1,1}]&&q[{x+2,0}])
ans++;
}
else
{
if(q[{x-1,0}]&&q[{x+1,0}])
ans++;
if(q[{x+1,0}]&&q[{x+2,1}])
ans++;
if(q[{x-1,0}]&&q[{x-2,1}])
ans++;
}
}
cout<<ans<<endl;
}
}
E. Klee 的 SUPER DUPER LARGE Array!!
直接二分
#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
ll ksm(ll x, ll y) { ll ans = 1; while (y) { if (y & 1)ans = (ans % mod * (x % mod)) % mod; x = (x % mod) * (x % mod) % mod % mod; y >>= 1; }return ans % mod % mod; }
ll gcd(ll x, ll y) { if (y == 0)return x; else return gcd(y, x % y); }
void fio() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); }
map<pair<ll,ll>,ll>q;
int main()
{
ll t;
cin>>t;
while(t--)
{
ll n,k;
cin>>n>>k;
ll l=1,r=n;
ll sum=(k+k+n-1)*n/2;
while(l<=r)
{
ll mid=(l+r)>>1;
ll u=(k+k+mid-1)*mid/2;
if(u>=sum-u)
{
r=mid-1;
}
else
l=mid+1;
}
if(l>1)
{
cout<<min(abs((k+(l-2)+k)*(l-1)/2-(sum-(k+(l-2)+k)*(l-1)/2)),abs((k+l-1+k)*l/2-(sum-(k+l-1+k)*l/2)))<<endl;
}
else
cout<<abs((k+l-1+k)*l/2-(sum-(k+l-1+k)*l/2))<<endl;
}
}
F. Firefly's Queries
这里其实数值和是存在一个周期的,直接左右两边尽量缩减然后形成周期的倍数比较好做
本人直接正向暴力了,\(WA\)了三发过
#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
//#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
ll ksm(ll x, ll y) { ll ans = 1; while (y) { if (y & 1)ans = (ans % mod * (x % mod)) % mod; x = (x % mod) * (x % mod) % mod % mod; y >>= 1; }return ans % mod % mod; }
ll gcd(ll x, ll y) { if (y == 0)return x; else return gcd(y, x % y); }
void fio() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); }
ll a[250000];
ll n;
ll ans = 0;
ll b[250000];
ll dfs(ll x, ll y)
{
if (x > y)
return 15666516;
// cout<<x<<" "<<y<<endl;
ll y1, x1;
ll u = x / n;//周期数
ll m = x % n;
if (x % n == 0)//刚好是这个周期得最后一个
{
u--;
u %= n;
if (u == 0)//第一周期
x1 = n;
else
x1 = u;
}
else
x1 = u % n + 1;
u %= n;
// cout<<u<<endl;
if (u == 0)//第0周期特判
y1 = n;
else
y1 = u;//周期数
// y1为右约束
ll g;
if (y1 >= x1)
g = 1;
else
g = 0;
ll cnt = 0;
// cout<<x1<<" "<<y1<<endl;
cnt = m;
if (g == 1)
x1 += max(cnt-1 , (ll)0);
else
{
if (x1 + cnt-1> n)
x1 = (x1 + cnt-1) % n,g=1;
else
x1 = x1 + cnt-1;
}
//cout<<x1<<" "<<y1<<endl;
ll dis = y - x + 1;
if (g == 1)
{
ans += b[min(x1 + dis - 1, y1)] - b[x1 - 1];
x += min(dis, y1 - x1 + 1);
}
else
{
ans += b[min(x1 + dis - 1, n)] - b[x1 - 1];
x += min(dis, n - x1 + 1);
x1 = 1;
if (x <= y)
{
dis = y - x + 1;
ans += b[min(x1 + dis - 1, y1)] - b[x1 - 1];
x += min(dis, y1 - x1 + 1);
}
}
return x;
}
int main()
{
fio();
ll t;
cin >> t;
while (t--)
{
ll q;
cin >> n >> q;
// cout<<n<<endl;
ll sum = 0;
b[0] = 0;
for (ll i = 1; i <= n; i++)
{
cin >> a[i];
sum += a[i];
b[i] = b[i - 1] + a[i];
}
while (q--)
{
ans = 0;
ll l1, r1;
cin >> l1 >> r1;
l1 = dfs(l1, r1);
// cout<<l1<<endl;
if (l1 > r1)
cout << ans << endl;
else
{
ll l = 0, r = n;
while (l < r)
{
ll mid = (l + r) >> 1;
if (l1 + mid * n - 1 >= r1)
{
r = mid;
}
else
l = mid + 1;
}
if (l1 + r * n - 1 == r1)
{
cout << ans + r * sum << endl;
}
else
{
r--;
ans += r * sum;
l1 = l1 + r * n - 1;
l1++;
ll u = dfs(l1, r1);
cout << ans << endl;
}
}
}
}
}
G1. Yunli's Subarray Queries (easy version)
求最长连续的数得先处理一下,直接减(1,2,3,...),因为连续且增大得数差值会变为同一个值,方便统计
然后维护队列加数组记录,这里加了个大数,使得负数情况消失。空间换时间
#include<iostream>
#include<map>
#include<set>
#include<vector>
#include<string.h>
#include<string>
#include<math.h>
#include<queue>
#include<bitset>
#include<stack>
#include<algorithm>
#include<deque>
using namespace std;
typedef long long ll;
ll a[200005];
ll b[200005];
ll e[400005];//桶排序
ll u[200005];
void fio()
{
ios::sync_with_stdio();
cin.tie(0);
cout.tie(0);
}
int main()
{
fio();
ll t;
cin >> t;
while (t--)
{
priority_queue<pair<ll,ll>>q;
ll n, k, m;
cin >> n >> k >> m;
for (ll i = 1; i <= n; i++)cin >> a[i];
for (ll i = 1; i <= n; i++)
{
b[i] = a[i] - i+200000;//偏差值
}
ll l = 0, r = 0;
for (ll i = 1; i <= n; i++)
{
if (l == 0 && r == 0)
{
l = r = i;
e[b[i]]++;//桶排序
q.push({ e[b[i]],b[i] });
if (r - l + 1 == k)
u[l] = q.top().first;
}
else
{
if (r - l + 1 < k)
{
r++;
e[b[i]]++;
while (!q.empty() && q.top().first != e[q.top().second])
{
q.pop();
}
q.push({ e[b[i]],b[i] });
if (r - l + 1 == k)
u[l] = q.top().first;
}
else if (r - l + 1 == k)
{
e[b[l]]--;
e[b[i]]++;
while (!q.empty() && q.top().first != e[q.top().second])
{
q.pop();
}
if (e[b[l]] != 0)
{
q.push({ e[b[l]],b[l] });
}
q.push({ e[b[i]],b[i] });
l++;
r++;
u[l] = q.top().first;
}
}
}
for (ll i = 1; i <= n; i++)
{
e[b[i]] = 0;
}
while (m--)
{
ll l, r;
cin >> l >> r;
cout << k-u[l] << endl;
}
}
}
G2. Yunli's Subarray Queries (hard version)
这里在G1得基础上用了堆栈+线段树
对照过正解,理应后面两题得用莫队做
#include<iostream>
#include<map>
#include<set>
#include<vector>
#include<string.h>
#include<string>
#include<math.h>
#include<queue>
#include<bitset>
#include<stack>
#include<algorithm>
#include<deque>
using namespace std;
typedef long long ll;
ll a[200005];
ll b[200005];
ll e[400005];//桶排序
ll u[200005];
ll f[200005];
vector<pair<ll,ll>>g[200005];
struct s
{
ll l, r;
ll v, lazy;
}p[250000<<2];
void build(ll i, ll l, ll r)
{
p[i].l = l;
p[i].r = r;
p[i].v=0;
p[i].lazy = -1;
if (l == r)
{
return;
}
build(i << 1, l, (l + r) >> 1);
build(i << 1 | 1, ((l + r) >> 1)+1, r);
}
void pushdown(ll i)
{
if (p[i].lazy>=0)
{
ll i1 = i << 1, i2 = i << 1 | 1;
p[i1].v = (p[i1].r - p[i1].l + 1) * p[i].lazy;
p[i2].v = (p[i2].r - p[i2].l + 1) * p[i].lazy;
p[i1].lazy = p[i].lazy;
p[i2].lazy = p[i].lazy;
p[i].v = p[i1].v + p[i2].v;
p[i].lazy = -1;
}
}
void ud(ll i, ll l, ll r,ll x)
{
if (l == p[i].l && r == p[i].r)
{
p[i].v = (p[i].r - p[i].l + 1) * x;
p[i].lazy = x;
return;
}
pushdown(i);
ll i1 = i << 1;
ll i2 = i << 1 | 1;
if (l <= p[i1].r)
{
if (r <= p[i1].r)
{
ud(i1, l, r, x);
}
else
ud(i1, l, p[i1].r, x);
}
if (r >= p[i2].l)
{
if (l >= p[i2].l)
ud(i2, l, r, x);
else
ud(i2, p[i2].l, r, x);
}
p[i].v = p[i1].v + p[i2].v;
}
ll query(ll i, ll l, ll r)
{
ll ans = 0;
if (l == p[i].l && r == p[i].r)
{
ans+=p[i].v;
return ans;
}
pushdown(i);
ll i1 = i<< 1;
ll i2 = i << 1 | 1;
if (l <= p[i1].r)
{
if (r <= p[i1].r)
ans += query(i1, l, r);
else
ans += query(i1, l, p[i1].r);
}
if (r >= p[i2].l)
{
if (l >= p[i2].l)
ans += query(i2, l, r);
else
ans += query(i2, p[i2].l, r);
}
return ans;
}
void fio()
{
ios::sync_with_stdio();
cin.tie(0);
cout.tie(0);
}
int main()
{
fio();
ll t;
cin >> t;
build(1, 1, 200020);
while (t--)
{
priority_queue<pair<ll, ll>>q;
ll n, k, m;
cin >> n >> k >> m;
ud(1, 1, n, 0);
for (ll i = 1; i <= n; i++)cin >> a[i];
for (ll i = 1; i <= n; i++)
{
b[i] = a[i] - i + 200000;//偏差值
}
ll l = 0, r = 0;
for (ll i = 1; i <= n; i++)
{
if (l == 0 && r == 0)
{
l = r = i;
e[b[i]]++;//桶排序
q.push({ e[b[i]],b[i] });
if (r - l + 1 == k)
u[l] = q.top().first;
}
else
{
if (r - l + 1 < k)
{
r++;
e[b[i]]++;
while (!q.empty() && q.top().first != e[q.top().second])
{
q.pop();
}
q.push({ e[b[i]],b[i] });
if (r - l + 1 == k)
u[l] = q.top().first;
}
else if (r - l + 1 == k)
{
e[b[l]]--;
e[b[i]]++;
while (!q.empty() && q.top().first != e[q.top().second])
{
q.pop();
}
if (e[b[l]] != 0)
{
q.push({ e[b[l]],b[l] });
}
q.push({ e[b[i]],b[i] });
l++;
r++;
u[l] = q.top().first;
}
}
}//处理好了
for (ll i = 1; i <= n; i++)
{
e[b[i]] = 0;
}
for (ll i = 1; i <= m; i++)
{
ll l, r;
cin >> l >> r;
g[l].push_back({ r - k + 1,i });;
}
stack<pair<ll,ll>>q1;
for (ll i = n-k+1; i >= 1; i--)
{
u[i] = k - u[i];
if (q1.empty())
{
q1.push({ i,u[i] });
ud(1, i, i, u[i]);
}
else
{
ll cnt = i;
while (!q1.empty() && q1.top().second > u[i])
{
cnt = q1.top().first;
q1.pop();
}
ud(1, i, cnt, u[i]);
q1.push({ cnt,u[i] });
}
for (auto j : g[i])
{
f[j.second] = query(1, i, j.first);
}
g[i].clear();
}
for (ll i = 1; i <= m; i++)
{
cout << f[i] << endl;
}
}
}
G3. Yunli's Subarray Queries (extreme version)
很久没写过莫队了,改天有激情时再补充