231108校内赛
T1 最大公约数
数据极水,啥都能过
第一种方法,暴力剪枝,直接飞过, \(\mathcal O(N^2\log n)\) 过 \(30\) 万不解释
玛德有人在提交时不写输出直接爆零
#include<bits/stdc++.h>
#define N 300010
using namespace std;
int n,k,ans,a[N];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int main(){
freopen("gcd.in","r",stdin);
freopen("gcd.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>k;
for(int i = 1;i<=n;i++){
cin>>a[i];
if(ans>=a[i])continue;
for(int j = 1;j<=i-k;j++){
if(ans>=a[j]) continue;
ans = max(ans,gcd(a[i],a[j]));
}
}
cout<<ans;
return 0;
}
第二种方法,正解,枚举答案,判断答案的所有倍数的第一次和最后一次出现的时间间隔是否不小于 \(k\)
从小到大或从大到小枚举答案都行
#include<bits/stdc++.h>
#define N 300010
using namespace std;
int n,k,ans,a[N],mn[N<<2],mx[N<<2];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int main(){
freopen("gcd.in","r",stdin);
freopen("gcd.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>k;
for(int i = 1;i<=1e6;i++) mn[i] = n+1,mx[i] = 0;
for(int i = 1;i<=n;i++){
cin>>a[i];
mn[a[i]] = min(mn[a[i]],i);
mx[a[i]] = max(mx[a[i]],i);
}
for(int i = 1e6;i>=1;i--){
int l = n+1,r = 0;
for(int j = i;j<=1e6;j+=i){
l = min(l,mn[j]);
r = max(r,mx[j]);
}
if(r-l>=k){
ans = i;
break;
}
}
cout<<ans;
return 0;
}
T2 子序列
问题本质就是每次删去字符,过程不同,有多少种删法
因为删除连续相同字符的效果是一样的,所以我们每回删除只删 \(s_i \neq s_{i+1}\) 的位置
考虑区间 \(dp\) ,枚举区间中最后一个删除的位置,这样对于左右两边而言就是独立的,分别计数
对于左右两边的还要乘上一个组合数 \(\binom {r-l} {i-l}\),\(r-l\) 代表剩余区间长度,\(i-l\) 代表当前点与左端点的距离,也就是左边区间的长度
对于限制来说,考虑删除第 \(i\) 个数时,它后面一定等于 \(s_{r+1}\) 因为他后边没有可删除的点了,所以一定是连续的一段,特判即可
这样就能保证 \(dp\) 的正确性了
时间复杂度 \(\mathcal O(n^3)\)
#include<bits/stdc++.h>
#define N 450
#define mod ((int)1e9+7)
#define int long long
using namespace std;
int n,a,ans,fac[N],inv[N],f[N][N];
char s[N];
inline int ksm(int x,int y){
int res = 1;
while(y){
if(y&1) res = res*x%mod;
x = x*x%mod;
y>>=1;
}
return res;
}
inline int C(int x,int y){
return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
signed main(){
freopen("sub.in","r",stdin);
freopen("sub.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>s+1;
fac[0] = 1;
for(int i = 1;i<N;i++)
fac[i] = fac[i-1]*i%mod;
inv[N-1] = ksm(fac[N-1],mod-2);
for(int i = N-2;i>=0;i--)
inv[i] = inv[i+1]*(i+1)%mod;
for(int i = 1;i<=n+1;i++)
f[i][i-1] = 1;
for(int len = 1;len<=n;len++){
for(int l = 1;l<=n-len+1;l++){
int r = l+len-1;
for(int i = l;i<=r;i++)
if(r==n||s[i]!=s[r+1]){
f[l][r] = (f[l][r]+C(len-1,i-l)*f[l][i-1]%mod*f[i+1][r]%mod)%mod;
}
}
}
cout<<f[1][n]<<"\n";
return 0;
}
T3 最短路
看不懂,上图
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
#define mod 998244353
using namespace std;
int tot,V;
int S,ans;
struct WORK{
int tot,xa[505],ya[505],xb[505],yb[505];
int n,m,pos_x[1005],pos_y[1005];
map<int,int> id_x,id_y;
int dis[505][505];
int id[505];
int f[505],h[505];
void bubble_sort1(){
for (int i=1;i<=tot;i++)
for (int j=1;j<tot;j++)
if (ya[j]>ya[j+1]){
swap(xa[j],xa[j+1]);
swap(ya[j],ya[j+1]);
swap(xb[j],xb[j+1]);
swap(yb[j],yb[j+1]);
}
return;
}
void bubble_sort2(){
for (int i=1;i<=tot;i++)
for (int j=1;j<tot;j++)
if (yb[id[j]]>yb[id[j+1]])swap(id[j],id[j+1]);
return;
}
void work(){
id_x[V]=1,pos_x[++n]=V;
id_y[V]=1,pos_y[++m]=V;
for (int i=1;i<=tot;i++){
if (id_x[xa[i]]==0){
id_x[xa[i]]=1;
pos_x[++n]=xa[i];
}
if (id_y[ya[i]]==0){
id_y[ya[i]]=1;
pos_y[++m]=ya[i];
}
if (id_x[xb[i]-1]==0){
id_x[xb[i]-1]=1;
pos_x[++n]=xb[i]-1;
}
if (id_y[yb[i]-1]==0){
id_y[yb[i]-1]=1;
pos_y[++m]=yb[i]-1;
}
}
sort(pos_x+1,pos_x+1+n);
for (int i=1;i<=n;i++)id_x[pos_x[i]]=i;
sort(pos_y+1,pos_y+1+m);
for (int i=1;i<=m;i++)id_y[pos_y[i]]=i;
for (int i=1;i<=tot;i++){
xa[i]=id_x[xa[i]];
ya[i]=id_y[ya[i]];
xb[i]=id_x[xb[i]-1]+1;
yb[i]=id_y[yb[i]-1]+1;
}
bubble_sort1();
for (int i=1;i<=tot;i++)
for (int j=i+1;j<=tot;j++)
if (xb[i]<=xa[j]&&yb[i]<=ya[j])dis[i][j]=1;
for (int k=1;k<=tot;k++)
for (int i=1;i<k;i++)
for (int j=k+1;j<=tot;j++)
if (dis[i][k]>0&&dis[k][j]>0)dis[i][j]=max(dis[i][j],dis[i][k]+dis[k][j]);
for (int i=1;i<=tot;i++)id[i]=i;
bubble_sort2();
for (int i=n;i>=1;i--){
memset(f,0,sizeof(f));
int p=tot;
for (int j=m;j>=1;j--){
while(p>=1&&ya[p]>=j){
if (xa[p]>=i){
f[p]=1;
for (int k=p+1;k<=tot;k++)
if (xa[k]>=i&&dis[p][k]>0)f[k]=max(f[k],dis[p][k]+1);
}
p--;
}
for (int k=1;k<=tot;k++)h[k]=V+1;
int s=0;
for (int k=1;k<=tot;k++){
int t=id[k];
if (f[t]>0){
int _f=f[t],_x=xb[t],_y=yb[t];
if (pos_x[_x]<h[_f]){
s=(s+1ll*(h[_f]-(pos_x[_x-1]+1))*(V-(pos_y[_y-1]+1)+1))%mod;
h[_f]=pos_x[_x-1]+1;
}
}
}
ans=(ans+1ll*(pos_x[i]-pos_x[i-1])*(pos_y[j]-pos_y[j-1])%mod*s)%mod;
}
}
return;
}
}work1,work2;
int main(){
freopen("path.in","r",stdin);
freopen("path.out","w",stdout);
cin>>tot>>V;
S=(1ll*V*(V+1)/2%mod*(-V-1)%mod+mod)%mod;
S=(S+1ll*V*(V+1)%mod*(2*V+1)%mod*((mod+1)/3)%mod)%mod;
S=1ll*S*V%mod*V%mod*2%mod;
for (int i=1;i<=tot;i++){
int xa,ya,xb,yb;
cin>>xa>>ya>>xb>>yb;
if (xa>xb)swap(xa,xb),swap(ya,yb);
if (ya<yb){
int t=++work1.tot;
work1.xa[t]=xa,work1.ya[t]=ya,work1.xb[t]=xb,work1.yb[t]=yb;
}
else{
int t=++work2.tot;
work2.xa[t]=xa,work2.ya[t]=V-ya+1,work2.xb[t]=xb,work2.yb[t]=V-yb+1;
}
}
work1.work();
work2.work();
cout<<(S-ans+mod)%mod<<endl;
return 0;
}
T4 树
纯纯码农题,很显然可以用树剖做
也没什么难的,不过稍微暴力一点也可以过
以下是暴力写法,其实能卡掉
#include<bits/stdc++.h>
#define N 100010
using namespace std;
struct edge{
int v,ne;
}e[N<<1];
int n,m,cnt,ans,h[N],tot,dfn[N],dep[N],siz[N],id[N],top[N],son[N],fa[N];
struct tree{
#define lc (p<<1)
#define rc ((p<<1)|1)
#define mid ((t[p].l+t[p].r)>>1)
struct node{
int l,r,prel,prer,sufl,sufr,flag;
}t[N<<2];
inline void pushnow(int p){
swap(t[p].prel,t[p].prer);
swap(t[p].sufl,t[p].sufr);
t[p].flag^=1;
}
inline void pushdown(int p){
if(!t[p].flag) return ;
pushnow(lc);pushnow(rc);
t[p].flag = 0;
}
inline void pushup(int p){
t[p].prel = min(t[lc].prel,t[rc].prel);
t[p].prer = min(t[lc].prer,t[rc].prer);
t[p].sufl = max(t[lc].sufl,t[rc].sufl);
t[p].sufr = max(t[lc].sufr,t[rc].sufr);
}
void build(int p,int l,int r){
t[p].l = l;t[p].r = r;
if(l==r){
t[p].prel = t[p].sufl = l;
t[p].prer = n+1;
t[p].sufr = 0;
return ;
}
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
}
void add(int p,int l,int r){
if(t[p].l>=l&&t[p].r<=r){
pushnow(p);
return ;
}
pushdown(p);
if(l<=mid) add(lc,l,r);
if(r>mid) add(rc,l,r);
pushup(p);
}
int querypre(int p,int v){
if(t[p].l==t[p].r) return t[p].sufr;
pushdown(p);
if(t[rc].prer<=v) return querypre(rc,v);
else return querypre(lc,v);
}
int querysuf(int p,int v){
if(t[p].l==t[p].r) return t[p].prer;
pushdown(p);
if(t[lc].sufr>=v) return querysuf(lc,v);
else return querysuf(rc,v);
}
}T;
void add(int u,int v){
e[++cnt].v = v;
e[cnt].ne = h[u];
h[u] = cnt;
}
void dfs1(int u){
siz[u] = 1;
for(int i = h[u];i;i = e[i].ne){
int v = e[i].v;
if(!dep[v]){
fa[v] = u;
dep[v] = dep[u]+1;
dfs1(v);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v]) son[u] = v;
}
}
}
void dfs2(int u,int tp){
top[u] = tp;dfn[u] = ++tot;
id[tot] = u;
if(son[u]) dfs2(son[u],tp);
for(int i = h[u];i;i = e[i].ne){
int v = e[i].v;
if(!top[v]) dfs2(v,v);
}
}
inline void update(int x,int y){
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
T.add(1,dfn[top[x]],dfn[x]);
x = fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(dfn[x]<dfn[y]) T.add(1,dfn[x]+1,dfn[y]);
}
inline int query(int x){
while(x){
int p = T.querypre(1,dfn[x]);
if(p==0) return 1;
if(p>=dfn[top[x]]) return p;
x = fa[top[x]];
}
return 1;
}
int main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i = 1;i<n;i++){
int u,v;cin>>u>>v;
add(u,v);add(v,u);
}
dep[1] = 1;
dfs1(1);
dfs2(1,1);
T.build(1,1,n);
while(m--){
int opt,x,y;
cin>>opt>>x;
if(opt==1){
cin>>y;
update(x,y);
}else{
ans = 1;
x = query(x);
int tmp = x+1;
while(tmp<x+siz[id[x]]){
if(T.querysuf(1,tmp)==tmp) tmp+=siz[id[tmp]];
else{
int t = min(x+siz[id[x]],T.querysuf(1,tmp))-1;
ans+=(t-tmp+1);tmp = t+1;
}
}
cout<<ans<<"\n";
}
}
return 0;
}
正解写法
//2024 HOPE IN VALUABLE
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
const int inf=1000000005;
int n,m,idx,mx,siz[N],fa[N],dep[N],son[N],top[N],dfn[N],poi[N],len[N]; vector<int>e[N];
namespace sgt{
struct Node{ int lc,rc,xmx,xmn,ymx,ymn,tag,sum; }t[N<<2]; int tot;
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
inline void pushup(int u){
t[u].xmx=max(t[t[u].lc].xmx,t[t[u].rc].xmx);
t[u].xmn=min(t[t[u].lc].xmn,t[t[u].rc].xmn);
t[u].ymx=max(t[t[u].lc].ymx,t[t[u].rc].ymx);
t[u].ymn=min(t[t[u].lc].ymn,t[t[u].rc].ymn);
t[u].sum=t[t[u].lc].sum+t[t[u].rc].sum;
}
inline void lzy(int u){
swap(t[u].xmx,t[u].ymx);
swap(t[u].xmn,t[u].ymn);
t[u].tag^=1;
}
inline void pushdown(int u){
if(!t[u].tag) return;
lzy(t[u].lc); lzy(t[u].rc);
t[u].tag=0;
}
inline void build(int &u,int l,int r){
u=++tot;
if(l==r){
t[u].xmx=t[u].xmn=l; t[u].sum=siz[poi[l]]-siz[son[poi[l]]];
t[u].ymx=-inf; t[u].ymn=inf;
return;
}
int mid=l+r>>1;
build(t[u].lc,l,mid); build(t[u].rc,mid+1,r);
pushup(u);
}
inline void flip(int u,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr) return lzy(u),void();
int mid=l+r>>1; pushdown(u);
if(ql<=mid) flip(t[u].lc,l,mid,ql,qr);
if(qr>mid) flip(t[u].rc,mid+1,r,ql,qr);
pushup(u);
}
inline int findl(int u,int l,int r,int x){
if(t[u].ymn>x) return -1;
if(l==r) return poi[l];
int mid=l+r>>1; pushdown(u);
if(t[t[u].rc].ymn<=x) return findl(t[u].rc,mid+1,r,x);
return findl(t[u].lc,l,mid,x);
}
inline int findr(int u,int l,int r,int x){
if(t[u].ymx<x) return -1;
if(l==r) return poi[l];
int mid=l+r>>1; pushdown(u);
if(t[t[u].lc].ymx>=x) return findr(t[u].lc,l,mid,x);
return findr(t[u].rc,mid+1,r,x);
}
inline int query(int u,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr) return t[u].sum;
int mid=l+r>>1; pushdown(u);
if(qr<=mid) return query(t[u].lc,l,mid,ql,qr);
if(ql>mid) return query(t[u].rc,mid+1,r,ql,qr);
return query(t[u].lc,l,mid,ql,qr)+query(t[u].rc,mid+1,r,ql,qr);
}
inline void add(int u,int l,int r,int x,int y){
if(l==r){
t[u].sum+=y;
return;
}
int mid=l+r>>1; pushdown(u);
if(x<=mid) add(t[u].lc,l,mid,x,y);
else add(t[u].rc,mid+1,r,x,y);
pushup(u);
}
} int rt[N];
inline void dfs1(int u){
siz[u]=1;
for(int v:e[u]){
if(v==fa[u]) continue;
fa[v]=u; dep[v]=dep[u]+1;
dfs1(v); siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
inline void dfs2(int u,int tp){
len[u]=1; top[u]=tp; dfn[u]=++idx; poi[idx]=u;
if(!son[u]) return;
dfs2(son[u],tp); len[u]=len[son[u]]+1;
for(int v:e[u]) if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
inline int querydown(int x){
if(!son[x]) return sgt::query(rt[top[x]],dfn[top[x]],dfn[top[x]]+len[top[x]]-1,dfn[x],dfn[x]);
int dwn=sgt::findr(rt[top[x]],dfn[top[x]],dfn[top[x]]+len[top[x]]-1,dfn[son[x]]);
if(dwn==-1) return sgt::query(rt[top[x]],dfn[top[x]],dfn[top[x]]+len[top[x]]-1,dfn[x],dfn[top[x]]+len[top[x]]-1);
return sgt::query(rt[top[x]],dfn[top[x]],dfn[top[x]]+len[top[x]]-1,dfn[x],dfn[fa[dwn]]);
}
inline int queryup(int x){
while(x){
int up=sgt::findl(rt[top[x]],dfn[top[x]],dfn[top[x]]+len[top[x]]-1,dfn[x]);
if(up!=-1) return querydown(up);
x=fa[top[x]];
}
return querydown(1);
}
inline void update(int x){
int tmp=querydown(top[x]);
while(x){
int ttmp=querydown(top[fa[top[x]]]);
sgt::flip(rt[top[x]],dfn[top[x]],dfn[top[x]]+len[top[x]]-1,dfn[top[x]],dfn[x]);
if(top[x]!=1){
if(sgt::findl(rt[top[x]],dfn[top[x]],dfn[top[x]]+len[top[x]]-1,dfn[top[x]])==-1)
sgt::add(rt[top[fa[top[x]]]],dfn[top[fa[top[x]]]],dfn[top[fa[top[x]]]]+len[top[fa[top[x]]]]-1,dfn[fa[top[x]]],querydown(top[x]));
else
sgt::add(rt[top[fa[top[x]]]],dfn[top[fa[top[x]]]],dfn[top[fa[top[x]]]]+len[top[fa[top[x]]]]-1,dfn[fa[top[x]]],-tmp);
}
x=fa[top[x]]; tmp=ttmp;
}
}
int main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
e[u].emplace_back(v);
e[v].emplace_back(u);
}
dfs1(1); dfs2(1,1);
for(int i=1;i<=n;i++)
if(top[i]==i)
sgt::build(rt[i],dfn[i],dfn[i]+len[i]-1);
while(m--){
int op; cin>>op;
if(op==1){
int x,y; cin>>x>>y;
update(x); update(y);
}
else{
int x; cin>>x;
cout<<queryup(x)<<'\n';
}
}
return 0;
}
梦与现实间挣扎着,所求为何
你可以借走我的文章,但你借不走我的智慧 虽然我是傻逼本文来自博客园,作者:cztq,转载请注明原文链接:https://www.cnblogs.com/cztq/p/17818092.html