比赛经历:感觉辽宁省赛都比较抽象不建议写
目录
A.伟大奋斗
简单签到
void solve(){
cin>>n;
cout << n-1949 << endl;
return ;
}
B.可莉的五子棋
直接暴力找四个方向或者是永bfs去扩展四个方向
char s[M][M];
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>s[i][j];
auto get = [&](char op){
int ans = 0;
vector l(n+5,vector<int>(m+5));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
l[i][j] = s[i][j] == op ? l[i][j-1] + 1 : 0;
if(l[i][j]>=5) ans++;
}
vector d(n+5,vector<int>(m+5));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
d[i][j] = s[i][j] == op ? d[i-1][j] + 1 : 0;
if(d[i][j]>=5) ans++;
}
vector lx(n+5,vector<int>(m+5));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
lx[i][j] = s[i][j] == op ? lx[i-1][j-1] + 1 : 0;
if(lx[i][j]>=5) ans++;
}
vector rx(n+5,vector<int>(m+5));
for(int i=1;i<=n;i++){
for(int j=m;j>=1;j--){
rx[i][j] = s[i][j] == op ? rx[i-1][j+1] + 1 : 0;
if(rx[i][j]>=5) ans++;
}
}
return ans;
};
cout << get('1') << ' ' << get('2') << endl;
return ;
}
C.消除死域点
发现删除当前这条链只会对从当前节点到头结点这链的点有贡献所以可以用树装数组维护可以活的点
vector<int> g[N];
int sz[N],tr[N];
int ans,res;
void add(int k,int x){
for(int i=k;i<=n;i+=lowbit(i)) tr[i]+=x;
}
int query(int k){
int res = 0;
for(int i=k;i;i-=lowbit(i)) res += tr[i];
return res;
}
void dfs1(int u,int fa){
sz[u] = 1;
for(auto&v:g[u]){
if(v==fa) continue;
dfs1(v,u);
sz[u] += sz[v];
}
}
void dfs2(int u,int fa){
if(sz[u]>m) add(sz[u],1);
for(auto&v:g[u]){
if(v==fa) continue;
int now = ans-query(m+sz[v]); // 表示原来是死的也就是sz[u]=m+1 要减去
res = min(res,now);
dfs2(v,u);
}
if(sz[u]>m) add(sz[u],-1);
}
void solve(){
cin>>n>>m;
for(int i=1;i<n;i++){
int a,b; cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs1(1,-1);
ans = 0;
for(int i=1;i<=n;i++) ans += (sz[i]-1)>=m; // 初始的时候有多少个死的
res = ans;
dfs2(1,-1);
cout << res << endl;
return ;
}
E.病毒危机
简单模拟即可
vector<int> g[N];
vector<int> pos;
bool st[N];
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
int t; cin>>t;
while(t--){
int x; cin>>x;
if(i==1) pos.push_back(x);
else g[x].push_back(i);
}
}
for(auto&x:pos)
for(auto&v:g[x])
st[v]=true;
int ans = 0;
st[1]=true;
for(int i=1;i<=n;i++) ans += st[i];
cout << ans << endl;
return ;
}
F.互质
感性分享一下就是暴力即可
void solve(){
LL x; cin>>x;
LL L = (x+3)/4, R = x/2;
while(L<=R){
if(__gcd(L,x)==1){
cout << L << endl;
return ;
}
L++;
}
cout << -1 << endl;
return ;
}
G.栈与公约数
典型的区间修改直接上线段树
vector<int> a;
int idx;
int w[N];
struct code{
int l,r;
int x;
int tag;
}tr[4*N];
void pushup(code&u,code&l,code&r){
u.x = __gcd(l.x,r.x);
}
void pushdown(code&u,code&l,code&r){
if(u.tag){
l.x = u.tag,l.tag = u.tag;
r.x = u.tag,r.tag = u.tag;
u.tag = 0;
}
}
void pushup(int u){
pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}
void pushdown(int u){
pushdown(tr[u],tr[u<<1],tr[u<<1|1]);
}
void build(int u,int l,int r){
if(l==r){
tr[u]={l,r};
return ;
}
tr[u]={l,r};
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,int x){
if(tr[u].l>= l && tr[u].r<=r){
tr[u].x = x;
tr[u].tag = x;
return ;
}
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) modify(u<<1,l,r,x);
if(r>mid) modify(u<<1|1,l,r,x);
pushup(u);
}
code query(int u,int l,int r){
if(tr[u].l>=l && tr[u].r<=r){
return tr[u];
}
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(r<=mid) return query(u<<1,l,r);
else if(l>mid) return query(u<<1|1,l,r);
else{
code res;
code ll=query(u<<1,l,r);
code rr=query(u<<1|1,l,r);
pushup(res,ll,rr);
return res;
}
}
void solve(){
cin>>n;
build(1,1,n);
while(n--){
int op,x; cin>>op;
if(op==1){
cin>>x;
++idx;
modify(1,idx,idx,x);
}
else if(op==2){
--idx;
}
else if(op==3){
code t = query(1,idx,idx);
cout << t.x << endl;
}
else{
cin>>x;
code t = query(1,idx-x+1,idx);
modify(1,idx-x+1,idx,t.x);
}
}
return ;
}
I.图的分割
搞懂题目意思其实就是最大生成树的最后一条边
struct code{
int a,b,w;
bool operator<(const code&t)const{
return w>t.w;
}
}e[N];
int p[N];
int find(int x){
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++) p[i]=i;
for(int i=1;i<=m;i++){
int a,b,w; cin>>a>>b>>w;
e[i]={a,b,w};
}
sort(e+1,e+1+m);
int cnt = 0;
for(int i=1;i<=m;i++){
auto [a,b,w]=e[i];
int fa=find(a),fb=find(b);
if(fa!=fb){
cnt++;
if(cnt==n-1){
cout << w << endl;
return ;
}
p[fa]=fb;
}
}
return ;
}
M.画画
简单画一画找找规律即可
void solve(){
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
s[i][j]=1;
int x,y;
if(n&1) x = 1,y = 1;
else x = 2, y = 2;
while(x<=n and y<=n){
s[x][y]=0;
x += 2, y += 2;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cout << s[i][j];
cout << endl;
}
return ;
}