2|0A. So I'll Max Out My Constructive Algorithm Skills
签到题,我们随便找一条路径,如果它合法就直接输出;否则把它reverse后输出即可
#include<cstdio>#include<iostream>#include<algorithm>#define RI register int#define CI const int&usingnamespace std;
constint N=70;
int t,n,h[N][N],s[N*N],cnt;
intmain(){
//freopen("A.in","r",stdin); freopen("A.out","w",stdout);for (scanf("%d",&t);t;--t)
{
RI i,j; for (scanf("%d",&n),i=1;i<=n;++i)
for (j=1;j<=n;++j) scanf("%d",&h[i][j]);
for (cnt=0,i=1;i<=n;++i)
if (i&1) for (j=1;j<=n;++j) s[++cnt]=h[i][j];
elsefor (j=n;j>=1;--j) s[++cnt]=h[i][j];
int l=0,g=0; for (i=1;i<cnt;++i)
l+=s[i]<s[i+1],g+=s[i]>s[i+1];
if (l>g) reverse(s+1,s+cnt+1);
for (i=1;i<=cnt;++i) printf("%d%c",s[i]," \n"[i==cnt]);
}
return0;
}
#include<cstdio>#include<iostream>#define int long long#define RI register int#define CI const int&usingnamespace std;
constint N=1e6+5,INF=1e18;
int t,n,k,p[N<<1],pos[N],g[N][2],f[N][2],ans;
classSegment_Tree{
private:
int mi[N<<2];
inlinevoidpushup(CI now){
mi[now]=min(mi[now<<1],mi[now<<1|1]);
}
public:
#define TN CI now=1,CI l=1,CI r=n#define LS now<<1,l,mid#define RS now<<1|1,mid+1,rinlinevoidbuild(TN){
mi[now]=0; if (l==r) return; int mid=l+r>>1; build(LS); build(RS);
}
inlinevoidupdata(CI pos,CI mv,TN){
if (l==r) return (void)(mi[now]=mv); int mid=l+r>>1;
if (pos<=mid) updata(pos,mv,LS); elseupdata(pos,mv,RS); pushup(now);
}
inlineintquery(CI pos,TN){
if (r<pos) return-1; if (mi[now]==1) return-1;
if (l==r) return l; int mid=l+r>>1,res=query(pos,LS);
if (~res) return res; returnquery(pos,RS);
}
#undef TN#undef LS#undef RS}SEG;
signedmain(){
//freopen("G.in","r",stdin); freopen("G.out","w",stdout);for (scanf("%lld",&t);t;--t)
{
RI i; for (scanf("%lld%lld",&n,&k),i=1;i<=n;++i)
scanf("%lld",&p[i]),f[i][0]=f[i][1]=INF,pos[p[i]]=i,p[i+n]=p[i];
if (n==k) { puts("0"); continue; } ans=INF;
for (SEG.build(),i=1;i<=k;++i) SEG.updata(p[n+i-1],1); g[p[n]][0]=SEG.query(p[n]);
for (i=n-1;i>=1;--i) SEG.updata(p[i],1),SEG.updata(p[i+k],0),g[p[i]][0]=SEG.query(p[i]);
for (SEG.build(),i=1;i<=k;++i) SEG.updata(p[n+1-i+1],1); g[p[n+1]][1]=SEG.query(p[n+1]);
for (i=n+2;i<=2*n;++i) SEG.updata(p[i],1),SEG.updata(p[i-k],0),g[p[i]][1]=SEG.query(p[i]);
//for (i=1;i<=n;++i) printf("g[%lld][0] = %lld\n",i,g[i][0]);//for (i=1;i<=n;++i) printf("g[%lld][1] = %lld\n",i,g[i][1]);int fir=-1; for (i=1;i<=n;++i) if (pos[i]>k) { fir=i; break; }
auto move=[&](CI x,CI y)
{
if (x>=y) returnmin(x-y,n-x+y); returnmin(y-x,n-y+x);
};
for (f[fir][0]=move(pos[fir],1),f[fir][1]=move(pos[fir],k),i=fir;i<=n;++i)
{
if (!~g[i][0]) ans=min(ans,f[i][0]); else {
int tmp=pos[g[i][0]]+1-pos[i];
while (tmp<1) tmp+=n; while (tmp>n) tmp-=n;
f[g[i][0]][0]=min(f[g[i][0]][0],f[i][0]+move(tmp,1));
f[g[i][0]][1]=min(f[g[i][0]][1],f[i][0]+move(tmp,k));
}
if (!~g[i][1]) ans=min(ans,f[i][1]); else {
int tmp=pos[g[i][1]]+k-pos[i];
while (tmp<1) tmp+=n; while (tmp>n) tmp-=n;
f[g[i][1]][0]=min(f[g[i][1]][0],f[i][1]+move(tmp,1));
f[g[i][1]][1]=min(f[g[i][1]][1],f[i][1]+move(tmp,k));
}
}
printf("%lld\n",ans);
}
return0;
}
9|0H. Permutation on Tree
噫,题目都没看,直接弃疗
10|0I. LCS Spanning Tree
这题纯徐神个人能力,我又是题目都没看
广义SAM的实际应用我只能说不好意思一点不会,但只要是字符串题我们队就无条件相信徐神
#include<bits/stdc++.h>constexprint $n = 4000000 + 5;
int go[$n][26], fa[$n], len[$n], las = 1, O = 1;
intinsert(char a){
int c = a - 'a', p = las;
if(go[p][c]) {
int q = go[p][c];
if(len[q] == len[p] + 1) return las = q;
int nq = ++O; len[nq] = len[p] + 1;
for(int i = 0; i < 26; ++i) go[nq][i] = go[q][i];
for(; p && go[p][c] == q; p = fa[p]) go[p][c] = nq;
fa[nq] = fa[q]; fa[q] = nq;
return las = nq;
}
int np = las = ++O;
len[np] = len[p] + 1;
for(int i = 0; i < 26; ++i) go[np][i] = 0;
for(; p && !go[p][c]; p = fa[p]) go[p][c] = np;
if(!p) return fa[np] = 1, las;
int q = go[p][c];
if(len[q] == len[p] + 1) return fa[np] = q, las;
int nq = ++O; len[nq] = len[p] + 1;
for(int i = 0; i < 26; ++i) go[nq][i] = go[q][i];
fa[nq] = fa[q]; fa[np] = fa[q] = nq;
for(; p && go[p][c] == q; p = fa[p]) go[p][c] = nq;
return las;
}
int n, Fa[$n];
std::string s[$n];
std::vector<std::pair<int, int> > host[$n];
std::priority_queue<std::pair<int, int> > pq;
inlineintfather(int a){
if(Fa[a] == a) return Fa[a];
return Fa[a] = father(Fa[a]);
}
intmain(){
// freopen("1.in", "r", stdin); std::ios::sync_with_stdio(false);
std::cin >> n;
for(int i = 1; i <= n; ++i) Fa[i] = i;
for(int i = 1; i <= n; ++i) {
las = 1;
std::cin >> s[i];
for(char c: s[i]) insert(c);
}
for(int i = 1; i <= n; ++i) {
int now = 1;
for(size_t j = 0; j < s[i].size(); ++j)
host[now = go[now][s[i][j] - 'a']].push_back({j + 1, i});
}
// return 0;for(int i = 1; i <= O; ++i) if(host[i].size()) {
std::sort(host[i].begin(), host[i].end());
for(int j = 0; j < host[i].size() - 1; ++j)
pq.push({host[i][j].first, i});
pq.push({host[i][0].first, i});
}
longlongsignedint ans = 0;
while(pq.size()) {
auto [_, i] = pq.top(); pq.pop();
if(!host[i].size()) continue;
if(host[i].size() == 1) {
// std::cerr << "debug " << i << ' ' << host[i].front().first << ' ' << _ << std::endl;if(fa[i]) {
if(host[fa[i]].size()) pq.push({host[fa[i]].back().first, fa[i]});
else pq.push({len[fa[i]], fa[i]});
host[fa[i]].push_back( std::pair<int, int>(len[fa[i]], host[i][0].second) );
}
host[i].pop_back();
continue;
}
// std::cerr << "debug " << i << ' ' << host[i].end()[-2].first << ' ' << _ << std::endl;auto [la, a] = host[i].back(); host[i].pop_back();
auto [lb, b] = host[i].back();
a = father(a), b = father(b);
if(a != b) {
Fa[a] = b;
// std::cout << "merge " << a << ' ' << b << ' ' << lb << std::endl; ans += lb;
}
}
std::cout << ans << std::endl;
return0;
}
11|0J. Colorful Tree
看这个过题数就是全场最难的题了,直接溜溜
12|0K. Link-Cut Tree
签到题,注意到其实就是用并查集维护什么时候成环就直接退出输出方案即可
刚开始想着怎么用并查集维护路径和方便,后来一想妈的直接暴力把森林建出来在上面爆搜就行了
#include<cstdio>#include<iostream>#include<vector>#include<algorithm>#define RI register int#define CI const int&usingnamespace std;
typedef pair <int,int> pi;
constint N=100005;
int t,n,m,x,y,fa[N],pre[N],lst[N]; vector <pi> v[N]; vector <int> ans;
inlineintgetfa(CI x){
return fa[x]!=x?fa[x]=getfa(fa[x]):x;
}
inlinevoidDFS(CI now,CI st,CI tar){
if (now==tar)
{
for (int x=tar;x!=st;x=pre[x]) ans.push_back(lst[x]); return;
}
for (auto [to,id]:v[now]) if (!~pre[to]) pre[to]=now,lst[to]=id,DFS(to,st,tar);
}
intmain(){
//freopen("K.in","r",stdin); freopen("K.out","w",stdout);for (scanf("%d",&t);t;--t)
{
RI i; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) pre[i]=-1,fa[i]=i,v[i].clear();
bool flag=0; for (i=1;i<=m;++i)
{
if (scanf("%d%d",&x,&y),flag) continue;
if (getfa(x)!=getfa(y)) fa[getfa(x)]=getfa(y),v[x].push_back(pi(y,i)),v[y].push_back(pi(x,i));
else {
flag=1; ans.clear(); pre[x]=0; DFS(x,x,y);
ans.push_back(i); sort(ans.begin(),ans.end());
for (RI j=0;j<ans.size();++j) printf("%d%c",ans[j]," \n"[j==ans.size()-1]);
}
}
if (!flag) puts("-1");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2022-09-12 COMPFEST 14 - Preliminary Online Mirror