首页 技术 正文
技术 2022年11月14日
0 收藏 437 点赞 3,689 浏览 9872 个字

  A:暴力赋值即可,并查集维护下一个未被赋值的位置。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 2000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int T,fa[N],len;
char s[N],ans[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
T=read();
for (int i=1;i<=2000001;i++) fa[i]=i;
while (T--)
{
scanf("%s",s);int m=strlen(s);
int n=read();
for (int i=1;i<=n;i++)
{
int x=read();
len=max(len,x+m-1);
for (int j=find(x);j<=x+m-1;j=find(j))
ans[j]=s[j-x],fa[j]=find(j+1);
}
}
for (int i=1;i<=len;i++)
if (find(i)==i) ans[i]='a';
printf("%s",ans+1);
return 0;
//NOTICE LONG LONG!!!!!
}

  B:显然应该连成菊花套链。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,k;
bool flag[N];
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
cin>>n>>k;
if (n%k==2||k==2&&n%k==0) cout<<2*((n-2)/k)+1<<endl;
else if (n%k==1) cout<<2*((n-1)/k)<<endl;
else cout<<2*((n-1)/k+1)<<endl;
for (int i=1;i<=k;i++) flag[i]=1;
for (int i=k+1;i<n;i++)
{
flag[i-k]=0;flag[i]=1;
printf("%d %d\n",i-k,i);
}
for (int i=1;i<=n;i++) if (flag[i]) printf("%d %d\n",n,i);
return 0;
//NOTICE LONG LONG!!!!!
}

  C:注意到字符集大小很小询问串长度很短,对每种字符每种长度分别维护bit即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
char s[N],t[N];
int n,q,tree[4][11][N];
int trans(char c)
{
if (c=='A') return 0;
if (c=='T') return 1;
if (c=='G') return 2;
if (c=='C') return 3;
}
int nxt(int x,int m,int r)
{
if (x>r) x-=m;
return x+(r-x)/m*m;
}//<=r u mod m=x mod m
void add(int x,int m,int k,int p)
{
while (k<=n)
{
tree[x][m][k]+=p;
int u=(k-1)/m+1;
u+=u&-u;
k=(u-1)*m+(k-1)%m+1;
}
}
int query(int x,int m,int k)
{
if (k<=0) return 0;
int s=0;
while (k>0)
{
s+=tree[x][m][k];
int u=(k-1)/m+1;
u-=u&-u;
k=(u-1)*m+(k-1)%m+1;
}
return s;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
scanf("%s",s+1);
n=strlen(s+1);
for (int i=1;i<=n;i++)
for (int j=1;j<=10;j++)
add(trans(s[i]),j,i,1);
q=read();
while (q--)
{
int op=read();
if (op==1)
{
int x=read();
char c=getc();
for (int j=1;j<=10;j++)
add(trans(s[x]),j,x,-1),
add(trans(c),j,x,1);
s[x]=c;
}
else
{
int l=read(),r=read();
scanf("%s",t);int m=strlen(t),ans=0;
for (int i=0;i<m;i++) ans+=query(trans(t[i]),m,nxt(l+i,m,r))-query(trans(t[i]),m,l+i-m);
printf("%d\n",ans);
}
}
return 0;
//NOTICE LONG LONG!!!!!
}

  D:先跑一棵MST。对于不在MST中的边,显然要使其满足条件,其权值应比MST中两点路径上的权值最大值小。倍增查一下即可。对于在MST上的边,其权值应比所有覆盖该边的非树边权值小。从小到大进行树链覆盖,并查集维护每个点第一个未被覆盖的祖先即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,p[N],dfn[N],f[N],deep[N],fa[N][19],E[N],ans[N],len[N][20],t,cnt;
bool flag[N];
struct data{int to,nxt,i,len;
}edge[N<<1];
struct data2
{
int x,y,z,i;
bool operator <(const data2&a) const
{
return z<a.z;
}
}e[N];
void addedge(int x,int y,int i,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].i=i,edge[t].len=z,p[x]=t;}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void dfs(int k)
{
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=fa[k][0])
{
fa[edge[i].to][0]=k;
E[edge[i].to]=edge[i].i;
len[edge[i].to][0]=edge[i].len;
deep[edge[i].to]=deep[k]+1;
dfs(edge[i].to);
}
}
int lca(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
for (int j=18;~j;j--) if (deep[fa[x][j]]>=deep[y]) x=fa[x][j];
if (x==y) return x;
for (int j=18;~j;j--) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];
return fa[x][0];
}
void cover(int x,int u,int y)
{
x=find(x);
while (deep[x]>deep[u])
{
ans[E[x]]=y-1;
f[x]=find(fa[x][0]);
x=find(x);
}
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),m=read();
for (int i=1;i<=m;i++) e[i].x=read(),e[i].y=read(),e[i].z=read(),e[i].i=i;
sort(e+1,e+m+1);
for (int i=1;i<=n;i++) f[i]=i;
for (int i=1;i<=m;i++)
if (find(e[i].x)!=find(e[i].y))
{
f[find(e[i].x)]=find(e[i].y);
addedge(e[i].x,e[i].y,e[i].i,e[i].z),addedge(e[i].y,e[i].x,e[i].i,e[i].z);
flag[i]=1;
}
fa[1][0]=1;dfs(1);
for (int j=1;j<=18;j++)
for (int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1],
len[i][j]=max(len[i][j-1],len[fa[i][j-1]][j-1]);
for (int i=1;i<=n;i++) f[i]=i;
for (int i=1;i<=m;i++)
if (!flag[i])
{
int x=e[i].x,y=e[i].y,u=lca(x,y);
cover(x,u,e[i].z);cover(y,u,e[i].z);
for (int j=18;~j;j--)
{
if (deep[fa[x][j]]>=deep[u]) ans[e[i].i]=max(ans[e[i].i],len[x][j]),x=fa[x][j];
if (deep[fa[y][j]]>=deep[u]) ans[e[i].i]=max(ans[e[i].i],len[y][j]),y=fa[y][j];
}
ans[e[i].i]--;
}
for (int i=2;i<=n;i++) if (find(i)==i) ans[E[i]]=-1;
for (int i=1;i<=m;i++) printf("%d ",ans[i]);
return 0;
//NOTICE LONG LONG!!!!!
}

  E:考虑如何判断某循环节长度是否合法,显然只要不存在字符不同(不包括?)的距离为其倍数的两位置即可。考虑求每种距离各有多少对字符不同。https://www.cnblogs.com/Gloid/p/9452441.html。然后暴力枚举倍数判断即可。略卡常,似乎FFT比NTT快。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1100000
#define P 998244353
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int T,n,a[N],b[N],c[N],f[N],r[N],ans[N];
char s[N];
void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
int ksm(int a,int k)
{
int s=1;
for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
return s;
}
int inv(int a){return ksm(a,P-2);}
void DFT(int *a,int n,int g)
{
for (int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|(i&1)*(n>>1);
for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
for (int i=2;i<=n;i<<=1)
{
int wn=ksm(g,(P-1)/i);
for (int j=0;j<n;j+=i)
{
int w=1;
for (int k=j;k<j+(i>>1);k++,w=1ll*w*wn%P)
{
int x=a[k],y=1ll*w*a[k+(i>>1)]%P;
a[k]=(x+y)%P,a[k+(i>>1)]=(x-y+P)%P;
}
}
}
}
void mul(int *a,int *b,int n)
{
DFT(a,n,3),DFT(b,n,3);
for (int i=0;i<n;i++) a[i]=1ll*a[i]*b[i]%P;
DFT(a,n,inv(3));
int t=inv(n);
for (int i=0;i<n;i++) a[i]=1ll*a[i]*t%P;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
T=read();
while (T--)
{
n=read();scanf("%s",s+1);
int t=1;while (t<(n<<1)) t<<=1;
for (int i=0;i<t;i++) a[i]=b[i]=c[i]=0;
for (int i=0;i<t;i++) f[i]=0;
for (int i=1;i<=n;i++) if (s[i]=='V') a[i]=1;
for (int i=0;i<n;i++) f[i]=2*(s[n-i]=='K');
mul(a,f,t);
for (int i=0;i<t;i++) f[i]=0;
for (int i=1;i<=n;i++) if (s[i]=='K') b[i]=8;
for (int i=0;i<n;i++) f[i]=s[n-i]=='V';
mul(b,f,t);
for (int i=0;i<t;i++) f[i]=0;
for (int i=1;i<=n;i++) if (s[i]=='V') c[i]=1;
for (int i=0;i<n;i++) f[i]=(P-4*(s[n-i]=='K'))%P;
mul(c,f,t);
int u=0;
for (int i=1;i<=n;i++)
{
bool flag=0;
for (int j=i;j<=n;j+=i)
if (a[n-j]+b[n-j]+c[n-j]) {flag=1;break;}
if (!flag) ans[++u]=i;
}
printf("%d\n",u);
for (int i=1;i<=u;i++) printf("%d ",ans[i]);printf("\n");
}
return 0;
//NOTICE LONG LONG!!!!!
}

  F:容易想到拆点bfs,点数过多。注意到只要边还没消失就可以在上面反复横跳,每隔2s就能返回一次原来的点。于是只将每个点根据时刻奇偶性拆成两个点。拆完后重建一下图,根据所连点的奇偶性稍微调整一下边的起止时间。

  这样可以在一个点逗留的时间段是连续(以2s为单位)的。考虑求出每个点最早什么时候能到,最晚什么时候走,这样就能得到答案了。

  用边更新答案。考虑将所有已确定最早能何时经过的边扔进小根堆。每次取出堆顶对该边终点进行更新。然后根据该终点信息更新以其为起点的所有尚未确定最早经过时间的边。若该点最晚离开时间超过了边的出现时间,就确定其最早经过时间。容易发现这样得到的时间一定是最优的,因为要么是其出现时间,要么是当前最早经过的边的时间。否则不管。为保证复杂度需要提前将以某点为起点的边按出现时间从小到大排序。大约就是跑了个魔改dij。

  另一种等价实现方法是一开始就把所有边扔进堆,具体见代码。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cassert>
using namespace std;
#define ll long long
#define N 500010
#define inf 1010000000
#define odd(i) ((i)+n)
#define even(i) (i)
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,t,first[N<<1],last[N<<1],cur[N<<1];
struct data
{
int x,y,l,r;
bool operator <(const data&a) const
{
return l>a.l;
}
};
priority_queue<data> q;
vector<data> e[N<<1];
void addedge(int x,int y,int l,int r){if (l>r) return;t++;q.push((data){x,y,l,r});}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),m=read();
for (int i=1;i<=m;i++)
{
int x=read(),y=read(),l=read(),r=read();
addedge(odd(x),even(y),l+(l%2==0),r-(r&1));
addedge(even(x),odd(y),l+(l&1),r-(r%2==0));
addedge(odd(y),even(x),l+(l%2==0),r-(r&1));
addedge(even(y),odd(x),l+(l&1),r-(r%2==0));
}
for (int i=1;i<=n*2;i++) first[i]=inf,last[i]=-1;
first[1]=last[1]=0;
while (!q.empty())
{
data u=q.top();q.pop();
if (last[u.x]>=u.l)
{
if (first[u.x]>=u.r) continue;
u.l=max(first[u.x],u.l);
last[u.y]=max(last[u.y],u.r);
first[u.y]=min(first[u.y],u.l+1);
while (cur[u.y]<e[u.y].size()&&last[u.y]>=e[u.y][cur[u.y]].l)
{
data v=e[u.y][cur[u.y]++];
if (first[u.y]>=v.r) continue;
v.l=max(first[v.x],v.l);
last[v.y]=max(last[v.y],v.r);
first[v.y]=min(first[v.y],v.l+1);
q.push(v);
}
}
else e[u.x].push_back(u);
}
//for (int i=1;i<=n*2;i++) cout<<first[i]<<' '<<last[i]<<endl;
if (min(first[odd(n)],first[even(n)])>=inf) cout<<-1;
else cout<<min(first[odd(n)],first[even(n)]);
return 0;
//NOTICE LONG LONG!!!!!
}

  

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,086
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,561
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,411
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,184
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,820
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,904