细微颗粒布满了整个房间 点燃通向毁灭实验的导线 所有成果于今天引爆炸裂 这不可逆爱恋从此灰飞烟灭
test49
可能是这辈子最后一场模拟赛了(?
文件改名
先删掉自环,连成图,发现是基环树森林可能扣掉一些边,不管怎么说就是要额外做环次操作了,那并查集看一下边数点数一不一样就好了。
#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pb push_back
using namespace std;
const int N=200005;
int n, m, dsu[N], siz[N], val[N], ans;
map<string,int> id;
int get(int x) { return x==dsu[x]?x:dsu[x]=get(dsu[x]); }
void merge(int x,int y) {
if((x=get(x))==(y=get(y))) return;
val[y]+=val[x], siz[y]+=siz[x], dsu[x]=y;
}
signed main() {
freopen("files.in","r",stdin);
freopen("files.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
up(i,1,n) {
string l, r;
cin >> l >> r;
if(l==r) { --ans; continue; }
if(!id[l]) id[l]=++m, dsu[m]=m, siz[m]=1;
if(!id[r]) id[r]=++m, dsu[m]=m, siz[m]=1;
merge(id[l],id[r]), ++val[get(id[r])];
}
up(i,1,m) if(dsu[i]==i&&val[i]==siz[i]) ++ans;
cout << n+ans << '\n';
return 0;
}
怪物猎人
贡献只有在 \(k+1\) 轮杀怪物减少 \((a+kd)(b+kd)=ab+(kd)^2+kd(a+b)\),那肯定按照 \(a+b\downarrow\) 来加,排序之后做背包即可。
#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define fir first
#define sec second
using namespace std;
const int N=3005;
int n, m, d, f[N][N];
pii a[N];
int calc(int i,int j) { return (a[i].fir+(j-1)*d)*(a[i].sec+(j-1)*d); }
signed main() {
freopen("hunter.in","r",stdin);
freopen("hunter.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m >> d;
up(i,1,n) cin >> a[i].fir;
up(i,1,n) cin >> a[i].sec;
sort(a+1,a+1+n,[](pii i,pii j){return i.fir+i.sec>j.fir+j.sec;});
up(i,1,n) {
up(j,1,i-1) f[i][j]=min(f[i-1][j],f[i-1][j-1]+calc(i,j));
f[i][i]=f[i-1][i-1]+calc(i,i);
}
while(m--) {
int h, ans;
cin >> h;
ans=lower_bound(f[n]+1,f[n]+1+n,h)-f[n]-1;
cout << ans << ' ';
}
return 0;
}
魔术帽游戏
操作先拆成两个平行的操作,对于依次有操作 \((a,b),(b,c)\) 连接对应的操作编号。查询就是找到第一个 \((x,)\) 然后一直跳直到 \(>r\),快速查找可以 vector,快速跳可以倍增。
#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
using namespace std;
const int N=500005, M=__lg(N)+1;
int n, m, q, T, tot, a[N], b[N], id[N][2], fa[N][M], lst[N];
vector<int> to[N];
signed main() {
freopen("magic.in","r",stdin);
freopen("magic.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m >> q, T=__lg(m);
up(i,1,m) cin >> a[i] >> b[i];
up(i,1,m) {
id[i][0]=++tot, id[i][1]=++tot;
to[a[i]].pb(id[i][0]), to[b[i]].pb(id[i][1]);
}
dn(i,m,1) {
fa[id[i][0]][0]=lst[b[i]];
fa[id[i][1]][0]=lst[a[i]];
lst[a[i]]=id[i][0], lst[b[i]]=id[i][1];
up(j,1,T) {
fa[id[i][0]][j]=fa[fa[id[i][0]][j-1]][j-1];
fa[id[i][1]][j]=fa[fa[id[i][1]][j-1]][j-1];
}
}
while(q--) {
int x, l, r;
cin >> x >> l >> r;
int p=lower_bound(to[x].begin(),to[x].end(),id[l][0])-to[x].begin();
if(p>=(int)to[x].size()||to[x][p]>id[r][1]) { cout << x << '\n'; continue; }
p=to[x][p];
dn(i,T,0) if(fa[p][i]&&fa[p][i]<=id[r][1]) p=fa[p][i];
if(p%2==1) cout << b[(p+1)/2] << '\n';
if(p%2==0) cout << a[p/2] << '\n';
}
return 0;
}
计算树
直接倍增就好了。
#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
using namespace std;
const int N=100005, M=__lg(N)+1, P=19491001;
int n, m, T, val[N], dep[N], fa[N][M];
pii f[N][M], g[N][M];
vector<pii> to[N];
pii operator+(const pii i,const pii j) {
return mp(i.fir*j.fir%P,(i.sec*j.fir%P+j.sec)%P);
}
void dfs(int x,int fad) {
dep[x]=dep[fad]+1, fa[x][0]=fad;
up(i,1,T) {
fa[x][i]=fa[fa[x][i-1]][i-1];
f[x][i]=f[x][i-1]+f[fa[x][i-1]][i-1];
g[x][i]=g[fa[x][i-1]][i-1]+g[x][i-1];
}
for(pii u:to[x]) {
int y=u.fir, opt=u.sec;
if(y==fad) continue;
if(opt==1) f[y][0]=mp(1,+val[x]), g[y][0]=mp(1,+val[y]);
if(opt==2) f[y][0]=mp(1,-val[x]), g[y][0]=mp(1,-val[y]);
if(opt==3) f[y][0]=mp(val[x],0), g[y][0]=mp(val[y],0);
dfs(y,x);
}
}
int lca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
dn(i,T,0) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if(x==y) return x;
dn(i,T,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i], y=fa[y][i];
return fa[x][0];
}
signed main() {
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m, T=__lg(n);
up(i,1,n) cin >> val[i], val[i]%=P;
up(i,2,n) {
int x, y, z;
cin >> x >> y >> z;
to[x].pb(mp(y,z));
to[y].pb(mp(x,z));
}
dfs(1,0);
while(m--) {
int x, y, p, sav;
pii ans, l(1,0), r(1,0);
cin >> x >> y;
sav=val[x], p=lca(x,y);
dn(i,T,0) if(dep[fa[x][i]]>=dep[p]) l=l+f[x][i], x=fa[x][i];
dn(i,T,0) if(dep[fa[y][i]]>=dep[p]) r=g[y][i]+r, y=fa[y][i];
ans=l+r;
cout << ((ans.fir*sav%P+ans.sec)%P+P)%P << '\n';
}
return 0;
}

浙公网安备 33010602011771号