Educational Codeforces Round 22
A. The Contest
显然先做好所有的然后一并提交
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1111;
void solve(){
____();
int n; cin >> n;
vector<int> A(n);
for(int i = 0; i < n; i++) cin >> A[i];
int s = accumulate(A.begin(),A.end(),0);
int m; cin >> m;
for(int i = 0; i < m; i++){
int l, r; cin >> l >> r;
if(s<=r){
cout << max(s,l) << endl;
return;
}
}
cout << -1 << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
B.The Golden Age
点数不会很多,全部找出来,然后在区间里找个最大间隔即可
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef unsigned long long int LL;
LL x, y, l, r;
void solve(){
cin >> x >> y >> l >> r;
set<LL> S;
vector<LL> v1, v2;
v1.push_back(1);
LL z = 1;
while(true){
if((r+10.) / x > z) z *= x;
else break;
v1.push_back(z);
}
v2.push_back(1);
z = 1;
while(true){
if((r+10.) / y > z) z *= y;
else break;
v2.push_back(z);
}
for(auto a : v1) for(auto b : v2) S.insert(a+b);
LL ret = 0ull;
vector<LL> A;
A.push_back(l-1);
for(auto x : S) if(x>=l and x<=r) A.push_back(x);
ret = max({ret,r-A.back()});
for(int i = 1; i < (int) A.size(); i++) ret = max(ret,A[i]-A[i-1]-1);
cout << ret << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
C. The Tag Game
显然要走到最远的位置,且在过程中不被抓到,那么只要枚举能走到的最远的位置就好了
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 2e5+7;
int n, x, dep[MAXN], par[MAXN], maxd[MAXN];
bool onp[MAXN];
vector<int> G[MAXN];
void dfs(int u, int fa){
dep[u] = dep[fa] + 1;
par[u] = fa;
for(int v : G[u]) if(v!=fa) dfs(v,u);
}
void dfs(int u){
maxd[u] = dep[u];
for(int v : G[u]) if(v!=par[u]){
dfs(v);
if(!onp[v]) maxd[u] = max(maxd[u],maxd[v]);
}
}
void solve(){
____();
cin >> n >> x;
for(int i = 1; i < n; i++){
int u, v; cin >> u >> v;
G[u].push_back(v); G[v].push_back(u);
}
dfs(1,0);
int cur = x;
while(cur) onp[cur] = true, cur = par[cur];
dfs(1);
int ret = 0;
for(int i = 2; i <= n; i++){
if(!onp[i]) continue;
if(dep[i]-dep[1]<=dep[x]-dep[i]) continue;
ret = max(ret,maxd[i]*2-2);
}
cout << ret << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
D. Two Melodies
考虑\(dp[i][j]\)表示第一个序列选到了\(i\),第二个序列选到了\(j\)这时候的长度和的最大值
注意不能通过\(dp[x][y]\)转移到\(dp[i][j]\),也即不能同时转移两个位置,会出现重复覆盖的问题
考虑固定一个进行转移,先枚举第一个序列的位置,然后第二个序列的位置可以从之前的位置转移过来,要求之前的位置满足
- 前面没有数
- 前面的数和当前数模\(7\)同余
- 前面的数和当前数的差值的绝对值为\(1\)
我们只要维护模\(7\)下各个模数的最大值和在各个值得情况下得最大值就能\(O(1)\)转移
网络流也可以做
view code
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define VI vector<int>
#define VL vector<LL>
#define pb push_back
#define ALL(V) V.begin(),V.end()
#define sci(x) scanf("%d",&x)
#define scl(x) scanf("%I64d",&x)
#define pii pair<int,int>
#define cmax(a,b) ((a) = (a) > (b) ? (a) : (b))
#define cmin(a,b) ((a) = (a) < (b) ? (a) : (b))
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 5555;
void solve(){
int n; sci(n);
VI A(n+1);
for(int i = 1; i <= n; i++) sci(A[i]);
vector<VI> f(n+1,VI(n+1));
VI maxmod(7,0), maxnum(100007,0);
for(int i = 0; i <= n; i++){
for(int j = 1; j < i; j++) cmax(maxmod[A[j]%7],f[i][j]), cmax(maxnum[A[j]],f[i][j]);
for(int j = i + 1; j <= n; j++){
f[j][i] = f[i][j] = max({f[i][0],maxmod[A[j]%7],maxnum[A[j]-1],maxnum[A[j]+1]}) + 1;
cmax(maxmod[A[j]%7],f[i][j]); cmax(maxnum[A[j]],f[i][j]);
}
fill(ALL(maxmod),0);
for(int j = 1; j <= n; j++) maxnum[A[j]] = 0;
}
int ret = 0;
for(int i = 0; i <= n; i++) cmax(ret,*max_element(ALL(f[i])));
cout << ret << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
E. Army Creation
建一棵主席树,同时记录某个颜色的点出现的次数,如果某个颜色出现的次数大于了\(k\),就删掉最先出现的那个位置
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 2e5+7;
int n, k;
set<int> pos[MAXN];
struct SegmentTree{
int root[MAXN], ls[MAXN<<5], rs[MAXN<<5], sum[MAXN<<5], tot;
void modify(int l, int r, int pos, int x, int &rt, int pre){
rt = ++tot;
ls[rt] = ls[pre]; rs[rt] = rs[pre]; sum[rt] = sum[pre] + x;
if(l+1==r) return;
int mid = (l + r) >> 1;
if(pos<mid) modify(l,mid,pos,x,ls[rt],ls[pre]);
else modify(mid,r,pos,x,rs[rt],rs[pre]);
}
int query(int l, int r, int L, int R, int rt){
if(L>=r or l>=R) return 0;
if(L<=l and r<=R) return sum[rt];
int mid = (l + r) >> 1;
return query(l,mid,L,R,ls[rt]) + query(mid,r,L,R,rs[rt]);
}
}ST;
void solve(){
____();
cin >> n >> k;
for(int i = 1; i <= n; i++){
int x; cin >> x;
int pre = ST.root[i-1];
if(pos[x].size()==k){
int rt = 0;
ST.modify(1,n+1,*pos[x].begin(),-1,rt,pre);
pre = rt;
pos[x].erase(pos[x].begin());
}
ST.modify(1,n+1,i,1,ST.root[i],pre);
pos[x].insert(i);
}
int q; cin >> q;
int lastans = 0;
while(q--){
int l, r; cin >> l >> r;
l = (l + lastans) % n + 1;
r = (r + lastans) % n + 1;
if(l>r) swap(l,r);
cout << (lastans = ST.query(1,n+1,l,n+1,ST.root[r])) << endl;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
F. Bipartite Checking
每条边有存在的一段时间,考虑线段树分治,由于相邻两个点颜色不能相同,考虑用可撤销扩展域并查集来做,如果两个点\(u\)和\(v\)连了边,就说明\(u\)和\(v\)是冲突的,那就\(u\)和\(v+n\)连边,\(u+n\)和\(v\)合并,如果\(u,v\)已经在同一个集合里了说明已经有冲突了
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
int n, m;
map<pair<int,int>, int> msk;
int f[MAXN<<1], dep[MAXN<<1];
bool bip[MAXN];
inline int findx(int x){ while(x!=f[x]) x = f[x]; return x; }
pair<int,int> merge(int u, int v){
int fu = findx(u), fv = findx(v);
if(dep[fu]<dep[fv]) swap(fv,fu);
auto p = make_pair(fv,dep[fu]);
f[fv] = fu;
if(dep[fu]==dep[fv]) dep[fu]++;
return p;
}
struct SegmentTree{
int l[MAXN<<2], r[MAXN<<2];
int head[MAXN<<2], nxt[MAXN<<6], tot;
pair<int,int> pr[MAXN<<6];
#define ls(rt) rt << 1
#define rs(rt) rt << 1 | 1
void build(int L, int R, int rt = 1){
l[rt] = L; r[rt] = R;
head[rt] = -1;
if(l[rt] + 1 == r[rt]) return;
int mid = (L + R) >> 1;
build(L,mid,ls(rt)); build(mid,R,rs(rt));
}
void insert(int L, int R, pair<int,int> e, int rt = 1){
if(L>=r[rt] or l[rt]>=R) return;
if(L<=l[rt] and r[rt]<=R){
nxt[tot] = head[rt];
pr[tot] = e; head[rt] = tot++;
return;
}
insert(L,R,e,ls(rt)); insert(L,R,e,rs(rt));
}
void dfs(int rt, bool ok = true){
stack<pair<int,int> > stk;
if(ok){
for(int i = head[rt]; ~i; i = nxt[i]){
int u = pr[i].first, v = pr[i].second;
if(findx(u)==findx(v)){
ok = false;
break;
}else{
assert(findx(u+n)!=findx(v+n));
if(findx(u)!=findx(v+n)){
stk.push(merge(u,v+n));
stk.push(merge(v,u+n));
}
}
}
}
if(l[rt] + 1 == r[rt]) bip[l[rt]] = ok;
else dfs(ls(rt),ok), dfs(rs(rt),ok);
while(!stk.empty()){
auto p = stk.top();
stk.pop();
dep[f[p.first]] = p.second; f[p.first] = p.first;
}
}
}ST;
void solve(){
____();
cin >> n >> m;
ST.build(1,m+1);
for(int i = 1; i <= m; i++){
int u, v; cin >> u >> v;
if(u>v) swap(u,v);
if(msk.count({u,v})) ST.insert(msk[{u,v}],i,{u,v}), msk.erase({u,v});
else msk.insert({{u,v},i});
}
for(auto p : msk) ST.insert(p.second,m+1,p.first);
for(int i = 1; i <= n * 2; i++) f[i] = i;
ST.dfs(1);
for(int i = 1; i <= m; i++) puts(bip[i]?"YES":"NO");
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}