大学课堂开设的数据结构课程,最后统计分数一般由 “线下作业、线下实验报告、机测和最后的期末理论考试” 组成。数据结构的理论知识和相对应的实验报告之前已经尽数和大家分享了,详情请点击下方链接:
手把手教你写八大数据结构实验报告( 代码&图文&内容丰富 !独此一家!)
今天,博主就和大家分享一下过往上机测验的AC_Code,方便大家测验结束后略作参考。不过讲真,那段时间的码风确实不怎么样!而且由于当时没有及时记录,只剩下下面这些 “残破不堪的代码了”,没有AC的代码博主会标记出来 [如果还记得的话,hhh],就是可惜不能附上对应的题面了(学校每次上机考试结束后,就无权限了…也怪我但是考完试比较懒QAQ,没有截图)
哦,对了!当时老师是让我做打星题,所以并不全面(和泉纱雾…
第一次(2020.03.18)
第1题
#include<bits/stdc++.h>
using namespace std;
int a[101][101];
bool vis[101][101];
int point[][3]={{-2,1},{-2,-1},{-2,2},{-2,-2},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1},{2,-2},{2,2}};
struct node {int x,y,bu;} q[10100];
void bfs(int x00,int y00)
{
int gx,gy,i,head=1,tail=1;
memset(vis,0,sizeof(vis));
q[tail].x=x00; q[tail].y=y00; q[tail].bu=0;
tail++; vis[x00][y00]=1;
while(head<tail)
{
int x=q[head].x,y=q[head].y, bu=q[head].bu;
if(x==1&&y==1)
{cout<<bu<<endl; break;}
for(i=0; i<12; i++)
{
gx=x+point[i][0]; gy=y+point[i][1];
if(gx>=1&&gx<=100&&gy>=1&&gy<=100&&vis[gx][gy]==0)
{
vis[gx][gy]=1;
q[tail].x=gx; q[tail].y=gy;
q[tail].bu=bu+1; tail++;
}
}
head++;
}
}
int main()
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
bfs(x1,y1);
bfs(x2,y2);
return 0;
}
第3题
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#define ll long long
#define maxn 1e9
/*xiaxv是个小菜鸡*/
int top[22];
int time[22];
int df[22][202],m,qwq;
float k=0;
int xm(int a,int b)
{
int i=0;
for(i=0;i<m;i++)
if(time[i]+df[i][top[i]]<=a)
{time[i]=0; return i;}
int min=999999,t=0;
for(i=0;i<m;i++)
{
if((time[i]+df[i][top[i]]-a)<min)
{
min=time[i]+df[i][top[i]]-a;
t=i;
}
}
time[t]=min; k+=min;
return t;
}
void hll(int a,int b)
{
int k,t=xm(a,b); top[t]++;
df[t][top[t]]=a+b;
}
int main()
{
int a,b,i,j;
while(~scanf("%d",&m))
{
scanf("%d",&qwq);
for(i=0; i<qwq; i++)
{
scanf("%d %d",&a,&b);
hll(a,b);
}
printf("%1.2f\n",k/qwq);
memset(time,0,sizeof(time));
memset(top,0,sizeof(top));
k=0;
}
return 0;
}
第5题(括号匹配)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1e5
using namespace std;
char s[1000];
int a[100],t1=0,t2=0,j=1;
int qwq(char s[])
{
int i=0;
while(i<strlen(s))
{
if(s[i]=='[') {a[++t2]=1; t1++;}
if(s[i]=='(') {a[++t2]=2; t1++;}
if(s[i]==']')
{
if(a[t2]==1) {t1--; t2--;}
else return 0;
}
if(s[i]==')')
{
if(a[t2]==2) {t1--; t2--;}
else return 0;
}
++i;
}
if(t1==0) return 1;
else return 0;
}
int main()
{
cin>>s;
if(qwq(s))cout<<"OK";
else cout<<"Wrong";
return 0;
}
第二次(2020.04.01)
第1题
#include <bits/stdc++.h>
using namespace std;
string s1,s2;
void qwq(int a1,int b1,int a2,int b2)
{
int i,j,k;
for(i=a2; i<=b2; i++)
{
k=0;
for(j=a1; j<=b1; j++)
if(s2[i]==s1[j])
{k=1; cout<<s1[j]; break;}
if(k) break;
}
if(j>a1) qwq(a1,j-1,1,b2);
if(j<b1) qwq(j+1,b1,1,b2);
}
int main()
{
cin>>s1>>s2;
qwq(0,s1.length()-1,0,s2.length()-1);
return 0;
}
第7题
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,i,j,x,y,rt,mr,sum,Maxx,q[120]={0};
int main()
{
cin>>n>>m;
for(i=1;i<=m;i++) cin>>x>>y,q[y]=x;
for(i=1;i<=n;i++)
if(q[i]==0) {rt=i; break;}
for(i=1;i<=n;i++)
{
sum=0;
for(j=1;j<=n;j++)
if(q[j]==i) sum++;
if(sum>Maxx) {Maxx=sum; mr=i;}
}
cout<<rt<<endl<<mr<<endl;
for(i=1;i<=n;i++)
if(q[i]==mr) cout<<i<<" ";
return 0;
}
第10题
#include <bits/stdc++.h>
using namespace std;
vector<char> pre,in,post;
map<int,char> Map;
int q[188],i,p;
void QWQ(int l,int r,int k)
{
if(l>=r) {q[k/2]=1; return;}
int m=distance(in.begin(),find(in.begin(),in.end(),pre[i++]));
Map[k]=in[m];
QWQ(l,m,k*2);
QWQ(m+1,r,k*2+1);
p=max(p,k);
}
int hhh(int k)
{
if(k>p) return 0;
if(q[k]) return q[k];
return q[k]=hhh(2*k)+hhh(2*k+1);
}
void print(int k)
{
if(!q[k]) return ;
for(int j=1; j<=q[k]; j++) cout<<Map[k];
cout<<endl;
print(2*k);
print(2*k+1);
}
int main()
{
int i;
string s1,s2;
cin>>s1>>s2;
for(i=0;i<s1.size();i++) pre.push_back(s1[i]);
for(i=0;i<s2.size();i++) in.push_back(s2[i]);
QWQ(0,s1.size(),1);
for(i=0; i<s1.size(); i++) hhh(1);
print(1);
cout<<endl;
}
第11题
#include <bits/stdc++.h>
#define ll long long
using namespace std;
typedef struct node;
typedef node *tree;
struct node {
char data;
bool check;
tree lchild,rchild;
};
tree root;
char c;
int x;
ll num,I,answeer,i;
void qwq(tree &bt,int sum,int number)
{
if(sum>x) return;
bt=new node;
bt->data=number;
bt->check=false;
qwq(bt->lchild,sum+1,number*2);
qwq(bt->rchild,sum+1,number*2+1);
}
int fgh(int depth,tree &bt)
{
if(depth==x) return bt->data;
if(bt->check) {bt->check=false; fgh(depth+1,bt->rchild);}
else {bt->check=true; fgh(depth+1,bt->lchild);}
}
int main()
{
cin>>x>>I;
qwq(root,1,1);
for(i=1;i<=I;i++) answeer=fgh(1,root);
cout<<answeer;
return 0;
}
第三次(2020.04.15)
第6题
#include<bits/stdc++.h>
#define fish first
#define lake second
using namespace std;
priority_queue<pair<int,int> >heap;
int f[105],t[105],d[105];
int main()
{
int n,m;
cin>>n;
for(int i=1; i<=n; i++) cin>>f[i];
for(int i=1; i<=n; i++) cin>>d[i];
for(int i=1; i<n; i++) cin>>t[i];
cin>>m;
int T=0,t1=0,ans=0,maxn=0;
for(int k=1; k<=n; k++)
{
T=m-t1;
ans=0;
while(!heap.empty()) {heap.pop();}
for(int i=1; i<=k; i++)
heap.push(make_pair(f[i],i));
while(T>0 && heap.top().fish>0)
{
pair<int ,int >a=heap.top();
heap.pop();
ans+=a.fish;
a.fish-=d[a.lake];
heap.push(a);
T--;
}
if(ans>maxn) maxn=ans;
t1+=t[k];
}
cout<<maxn<<endl;
return 0;
}
第7题
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int M=305,N=(1<<8)+1;
int a[M],to[N];
ll w[N],dp[M][M][N],g[3];
const ll inf=-1e9;
ll ans = inf;
int main()
{
int n,k,i,s,L,mid;
cin>>n>>k;
for(i=1; i<=n; i++) scanf("%1d",&a[i]);
for(s=0; s<(1<<k); s++) scanf("%d%lld",&to[s],&w[s]);
memset(dp,0x8f,sizeof(dp));
for(i=1;i<=n;i++) dp[i][i][a[i]]=0;
for(L=2;L<=n;L++)
for(i=1;i<=n-L+1;i++)
{
int j=i+L-1,len=j-i;
while(len>k-1) len-=(k-1);
for(mid=j; mid>0; mid-=k-1)
{
for(s=0; s<(1<<len); s++)
if(dp[i][mid - 1][s] > inf)
{
if(dp[mid][j][1]>inf)
dp[i][j][s<<1|1]=max(dp[i][j][s<<1|1],dp[i][mid-1][s]+dp[mid][j][1]);
if(dp[mid][j][0] > inf)
dp[i][j][s<<1] = max(dp[i][j][s<<1], dp[i][mid - 1][s] + dp[mid][j][0]);
}
}
if(len==k-1)
{
g[0]=g[1]=inf;
for(s=0; s<(1<<k); s++)
if(dp[i][j][s]>inf)
g[to[s]] = max(g[to[s]], dp[i][j][s] + w[s]);
dp[i][j][1] = g[1]; dp[i][j][0] = g[0];
}
}
for(s=0; s<(1<<k); s++) ans = max(ans, dp[1][n][s]);
cout<<ans;
}
第10题
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node {
int meg;
ll c;
node() {meg=0; c=0;}
friend bool operator<(node n1,node n2) {
if(n1.c!=n2.c)
return n1.c>n2.c;
return n1.meg>n2.meg;
}
};
priority_queue<node> q;
int n,k,i;
ll w[210000];
node cnt[15];
int main()
{
cin>>n>>k;
for(i=1;i<=n;i++) scanf("%lld",&w[i]);
while((n-1)%(k-1)) w[++n]=0;
for(i=1;i<=n;i++) {node tmp;tmp.c=w[i]; tmp.meg=0; q.push(tmp);}
ll ans=0;
while(q.size()!=1)
{
for(i=1;i<=k;i++) cnt[i]=q.top(),q.pop();
node tmp; tmp.meg=0; tmp.c=0;
for(i=1;i<=k;i++) tmp.c+=cnt[i].c,tmp.meg=max(tmp.meg,cnt[i].meg);
tmp.meg++; ans+=tmp.c; q.push(tmp);
}
node tmp=q.top();
cout<<ans<<endl<<tmp.meg<<endl;
return 0;
}
第11题
#include <bits/stdc++.h>
#define N 7000005
using namespace std;
int n,m,q,u,v,t;
bool cmp(const int &a,const int &b) {
return a>b;
}
priority_queue<int>ans;
int cut1[N],cut2[N],now[N];
int sum,h0,h1,h,t0,t1,t2;
double p;
int main()
{
scanf("%d %d %d %d %d %d",&n,&m,&q,&u,&v,&t);
p=(double)u/v;
int tmp;
for(t0=1; t0<=n; t0++)
scanf("%d",&now[t0]);
t0--;
t1=t2=0;
h0=h1=h2=1;
sort(now+1,now+t0+1,cmp);
int top;
for(int i=1; i<=m; i++)
{
if(h0>t0) {
if(cut1[h1]>cut2[h2]) top=cut1[h1++];
else top=cut2[h2++];
}
else if(now[h0]>=cut1[h1] && now[h0]>=cut2[h2])
top=now[h0],h0++;
else if(cut1[h1]>=cut2[h2] && now[h0]<=cut1[h1])
top=cut1[h1],h1++;
else top=cut2[h2],h2++;
top+=sum;
int a1=floor(p*(double)top),a2=top-a1;
sum+=q;
a1-=sum,a2-=sum;
cut1[++t1]=a1,cut2[++t2]=a2;
if(i%t==0) printf("%d ",top);
}
putchar('\n');
for(int i=h0; i<=t0; i++)
ans.push(now[i]);
for(int i=h1; i<=t1; i++)
ans.push(cut1[i]);
for(int i=h2; i<=t2; i++)
ans.push(cut2[i]);
for(int i=1; ans.size(); i++)
{
if(i%t==0) printf("%d ",ans.top()+sum);
ans.pop();
}
return 0;
}
第四次
3.最小瓶颈路 加强版
#include <bits/stdc++.h>
const int MAXN=1e6+10, mod=1e9+7;
using namespace std;
inline int read() {
char c=getchar();
int x=0, f=1;
while (c<'0' || c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
return x*f;
}
int N,M,fa[MAXN],tot,val[MAXN],id[MAXN][21],num,dfn[MAXN],dep[MAXN],lg2[MAXN];
struct Edge {
int u, v, w;
bool operator<(const Edge &rhs) const { return w < rhs.w; }
} E[MAXN];
vector<int> v[MAXN];
int find(int x) {return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}
void Kruskal()
{
for (int i=1; i<=2*N; i++) fa[i]=i;
tot = N;
for(int i=1; i<=M; i++) {
int x = find(E[i].u), y = find(E[i].v);
if(x==y) continue;
val[++tot] = E[i].w;
v[tot].push_back(x);
v[tot].push_back(y);
v[x].push_back(tot);
v[y].push_back(tot);
fa[x] = tot;
fa[y] = tot;
}
}
void dfs(int x, int fa)
{
dfn[x] = ++num;
dep[x] = dep[fa]+1;
id[num][0] = x;
for (int i=0, to; i<v[x].size(); i++) {
if((to=v[x][i])==fa) continue;
dfs(to, x);
id[++num][0] = x;
}
}
void RMQ() {
for(int i=2; i<=num; i++) lg2[i] = lg2[i>>1] + 1;
for(int j=1; j<=20; j++)
for(int i=1; i+(1<<j)-1<=num; i++) {
int r = i+(1<<(j-1));
id[i][j] = (dep[id[i][j-1]] < dep[id[r][j-1]]) ? id[i][j-1] : id[r][j-1];
}
}
int A, B, C, P;
inline int rnd() { return A = (A*B+C) % P; }
int LCA(int x, int y) {
x = dfn[x];
y = dfn[y];
if (x > y)
swap(x, y);
int k = lg2[y - x + 1];
return dep[id[x][k]] < dep[id[y - (1 << k) + 1][k]] ? id[x][k] : id[y - (1 << k) + 1][k];
}
int main() {
N = read();
M = read();
for (int i = 1; i <= M; i++) {
int x = read(), y = read(), z = read();
E[i] = (Edge){ x, y, z };
}
sort(E + 1, E + M + 1);
Kruskal();
dfs(tot, 0);
RMQ();
int ans = 0, Q = read();
A = read(); B = read();
C = read(); P = read();
while (Q--) {
int u = rnd() % N + 1, v = rnd() % N + 1;
(ans += val[LCA(u, v)]) %= mod;
}
printf("%d", ans);
return 0;
}
10. 最小生成树计数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=101;
const int M=1010;
const int p=31011;
inline int read(){
int X=0,w=0;char ch=0;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
struct node{
int u,v,w;
}e[M];
struct range{
int l,r;
}a[M];
int fa[N],t[M],n,m,k,sum;
inline bool cmp(node a,node b){
return a.w<b.w;
}
int find(int x){
if(fa[x]==x)return x;
return find(fa[x]);
}
inline void unionn(int x,int y){
fa[x]=y;
}
inline void destory(int x,int y){
fa[x]=x;fa[y]=y;
}
void dfs(int l,int r,int d,int w){
if(l>r){
if(d==t[w])sum=(sum+1)%p;
return;
}
if(r-l+1+d<t[w])return;
int u=find(e[l].u),v=find(e[l].v);
if(u!=v&&d<t[w]){
unionn(u,v);
dfs(l+1,r,d+1,w);
destory(u,v);
}
dfs(l+1,r,d,w);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=m;i++){
e[i].u=read(),e[i].v=read(),e[i].w=read();
}
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n;i++)fa[i]=i;
int cnt=0;
for(int i=1;i<=m;i++)
{
if(e[i].w!=e[i-1].w)
{
a[++k].l=i;
a[k-1].r=i-1;
}
int u=e[i].u,v=e[i].v;
u=find(u),v=find(v);
if(u!=v)t[k]++,cnt++,unionn(u,v);
}
a[k].r=m;
if(cnt!=n-1) {
puts("0"); return 0;
}
int ans=1;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=k;i++)
{
if(!t[i]) continue;
sum=0;
dfs(a[i].l,a[i].r,0,i);
ans=(ll)ans*sum%p;
for(int j=a[i].l;j<=a[i].r;j++)
{
int u=e[j].u,v=e[j].v;
u=find(u),v=find(v);
if(u!=v)unionn(u,v);
}
}
printf("%d\n",ans);
return 0;
}
11. 菜肴制作
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int mxn=2e5+5;
int n,m,cnt,hd[mxn];
inline int read() {
char c=getchar(); int x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline void chkmax(int &x,int y) {if(x<y) x=y;}
inline void chkmin(int &x,int y) {if(x>y) x=y;}
struct ed {
int to,nxt;
}t[mxn<<1];
inline void add(int u,int v) {
t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}
int tot,in[mxn],ans[mxn],vis[mxn];
struct Node {
int x,y;
friend bool operator < (Node a,Node b) {
if(a.y==b.y) return a.x>b.x;
return a.y>b.y;
}
}nod[mxn];
int dfs(int u) {
int mi=u;
for(int i=hd[u];i;i=t[i].nxt) {
int v=t[i].to;
chkmin(mi,dfs(v));
}
nod[u].x=u,nod[u].y=mi;
return mi;
}
priority_queue<int> q;
int main()
{
int T; T=read();
while(T--) {
memset(hd,0,sizeof(hd));
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
tot=cnt=0;
n=read(); m=read(); int u,v,flag=0;
for(int i=1;i<=m;++i) {
u=read(); v=read();
add(v,u); ++in[u];
}
for(int i=1;i<=n;++i) if(in[i]==0) q.push(i);
while(!q.empty()) {
u=q.top(); q.pop(); vis[u]=1; ans[++tot]=u;
for(int i=hd[u];i;i=t[i].nxt) {
v=t[i].to; --in[v];
if(in[v]==0) q.push(v);
}
}
for(int i=1;i<=n;++i) if(!vis[i]) {puts("Impossible!");flag=1;break ;}
if(flag) continue ;
for(int i=n;i>=1;--i) printf("%d ",ans[i]); printf("\n");
}
return 0;
}
13. 蛋糕
#include<bits/stdc++.h>
using namespace std;
unsigned long long t,n,r,h;
bool vis[1005],jude;
struct node{
double x,y,z;
}hole[10005];
bool pd(node a,node b) {
long long d;
d=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z);
if(d<=4*r*r) return true;
else return false;
}
void dfs(int i)
{
if(jude)return ;
if(hole[i].z+r>=h)
{
jude=1;
return ;
}
for(int j=1;j<=n;j++)
{
if(pd(hole[i],hole[j])&&!vis[j])
{
vis[j]=1;
dfs(j);
}
}
}
int main()
{
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
scanf("%d%d%d",&n,&h,&r);
memset(vis,0,sizeof(vis));jude=0;
for(int j=1;j<=n;j++)
scanf("%lf%lf%lf",&hole[j].x,&hole[j].y,&hole[j].z);
for(int k=1;k<=n;k++)
if(hole[k].z<=r)
{
vis[k]=1;
dfs(k);
}
if(jude)printf("Yes\n");
else printf("No\n");
}
}
第五次
7.欧拉回路
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
const int M=1000010;
bool flag[M];
int in[N],out[N];
int type,n,m,tot=1,x,y;
int head[N],ver[M],nxt[M];
vector<int> ans;
void add(int u,int v) {
ver[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
void dfs(int x) {
for(int &i=head[x],y; y=ver[i],i; i=nxt[i]) {
int c=(type==1?i/2:i-1);
int sig=i%2;
if(flag[c]) continue;
flag[c]=1;
dfs(y);
if(type==1) ans.push_back(sig?-c:c);
else ans.push_back(c);
}
}
int main () {
scanf("%d%d%d",&type,&n,&m);
for(int i=1; i<=m; i++) {
scanf("%d%d",&x,&y);
add(x,y);
if(type==1) add(y,x);
out[x]++;
in[y]++;
}
if(type==1) {
for(int i=1; i<=n; i++)
if((in[i]+out[i])%2) {
printf("NO\n");
return 0;
}
}
else{
for(int i=1; i<=n; i++) {
if(in[i]!=out[i]) {
printf("NO\n");
return 0;
}
}
}
for(int i=1; i<=n; i++)
if(head[i]) {dfs(i); break;}
if(ans.size()!=m) {cout<<"NO"<<endl; return 0;}
cout<<"YES"<<endl;
for(int i=m-1;i>=0;i--) cout<<ans[i]<<" ";
cout<<endl;
return 0;
}
11.物流运输(最短路和DP)
思路: 这道题结合了最短路和DP,其中最短路由 SPFA 完成,
图由邻接矩阵储存。用 t[i][j]表示第i天至第j天。从起点到终点的最短路。f[i]储存至第i天的最小花费。可以轻松得到 f[i] = min{f[i],f[j]+k+t[j+1][i]*(i-j)}。输出f[n]得解。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct data{ //邻接矩阵存边长
int next,to,w;
}e[801];
int ne,head[21]; //head邻接矩阵伪头结点
int n,m,k;
bool flag[101][21]; //第i(0<i<=n)天j(0<j<=m)码头是否报废
ll t[101][101],f[101]; //t数组存第i(0<i<=n)天至第j(0<j<=n)天起点到终点的最短路;
void insert(int u,int v,int w){ //加入新边
ne++;
e[ne].to=v;
e[ne].w=w;
e[ne].next=head[u];
head[u]=ne;
}
int spfa(int a,int b){
bool block[21];
int dis[21],q[500],inq[21];
memset(block,0,sizeof block);
memset(dis,127,sizeof dis);
memset(inq,0,sizeof inq);
for(int i=a;i<=b;i++)
for(int j=1;j<=m;j++)
if(flag[i][j]) block[j]=1; //a天至b天之间j节点是否报废
q[0]=1; //队列
inq[1]=1; //标记该节点有无入队
dis[1]=0;
int t=0,w=1; //队头与队尾
while(t<w) //SPFA
{
int p=head[q[t]];
while(p)
{
if(!block[e[p].to]&&dis[e[p].to]>dis[q[t]]+e[p].w)
{
dis[e[p].to]=dis[q[t]]+e[p].w;
if(!inq[e[p].to]){
q[w++]=e[p].to;
inq[e[p].to]=1;
}
}
p=e[p].next;
}
inq[q[t]]=0; t++;
}return dis[m];
}
void dp(){
for(int i=1;i<=n;i++){
f[i]=(ll)t[1][i]*i;
for(int j=0;j<i;j++) f[i]=min(f[i],f[j]+k+t[j+1][i]*(i-j));
}
}
int main()
{
int q;
cin>>n>>m>>k>>q;
for(int i=1;i<=q;i++) {//加边
int x,y,z;
cin>>x>>y>>z;
insert(x,y,z);
insert(y,x,z);
}
int d; cin>>d;
for(int i=1;i<=d;i++){ //记录报废节点
int x,y,z;
cin>>x>>y>>z;
for(int j=y;j<=z;j++) flag[j][x]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) t[i][j]=spfa(i,j);
dp();
cout<<f[n]<<endl;
return 0;
}
12.逛公园(dfs,dijkstra)
#include<bits/stdc++.h>
const int K=55,N=100005,M=500005;
using namespace std;
int n,m,k,p,t1,t2,flag;
int d[N],f[N][K],vis[N][K];
int first[N],v[M],w[M],nxt[M];
int First[N],V[M],W[M],Nxt[M];
priority_queue<pair<int,int> >q;
void add(int x,int y,int z){
nxt[++t1]=first[x];
first[x]=t1;
v[t1]=y;
w[t1]=z;
}
void Add(int x,int y,int z){
Nxt[++t2]=First[x];
First[x]=t2;
V[t2]=y;
W[t2]=z;
}
void init()
{
t1=t2=flag=0;
memset(f,-1,sizeof(f));
memset(first,0,sizeof(first));
memset(First,0,sizeof(First));
}
void dijkstra(int s)
{
int x,y,i;
memset(d,127/3,sizeof(d));
q.push(make_pair(0,s));d[s]=0;
while(!q.empty())
{
x=q.top().second;q.pop();
for(i=first[x];i;i=nxt[i])
{
y=v[i];
if(d[y]>d[x]+w[i])
{
d[y]=d[x]+w[i];
q.push(make_pair(-d[y],y));
}
}
}
}
int dfs(int now,int val)
{
if(~f[now][val]) return f[now][val];
int i,to,num;f[now][val]=0,vis[now][val]=1;
for(i=First[now];i;i=Nxt[i])
{
to=V[i];
num=d[now]-d[to]+val-W[i];
if(num<0) continue;
if(vis[to][num]) flag=1;
f[now][val]=(f[now][val]+dfs(to,num))%p;
}
vis[now][val]=0;
return f[now][val];
}
int main()
{
int x,y,z,i,T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d%d%d%d",&n,&m,&k,&p);
for(i=1;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z),Add(y,x,z);
}
int ans=0;
dijkstra(1);
for(i=0;i<=k;++i) dfs(n,i);
if(flag) {puts("-1");continue;}
memset(f,-1,sizeof(f));
f[1][0]=1;
for(i=0;i<=k;++i) ans=(ans+dfs(n,i))%p;
cout<<ans<<endl;
}
return 0;
}
第六次
第1题 模式字符串(分治+hash)
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define ui unsigned int
#define inf 0x7f7f7f7f
using namespace std;
const int N=1e6,base=974531;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
int x=0,f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline int read(){
int x=0,f=1; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
}
int pre[(N<<1)+10],now[N+10],child[(N<<1)+10];
int size[N+10],Df[N+10],Up[N+10],Dn[N+10],sup[N+10],sdn[N+10];
ull Suf[N+10],Pre[N+10];
bool vis[N+10];
char s[N+10];
int tot,root,Max,Ans,n,m;
void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
void insert(int x,int y){join(x,y),join(y,x);}
void Get_root(int x,int fa,int sz){
int res=0; size[x]=1;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa||vis[son]) continue;
Get_root(son,x,sz);
size[x]+=size[son];
res=max(res,size[son]);
}
res=max(res,sz-size[x]);
if (res<Max) Max=res,root=x;
}
void solve(int x,int fa,ull res,int Deep){
res=res*base+s[x],Df[x]=Deep;
if (res==Pre[Deep]) Up[(Deep-1)%m+1]++,Ans+=sdn[m-(Deep-1)%m];
if (res==Suf[Deep]) Dn[(Deep-1)%m+1]++,Ans+=sup[m-(Deep-1)%m];
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa||vis[son]) continue;
solve(son,x,res,Deep+1);
Df[x]=max(Df[x],Df[son]);
}
}
void divide(int x){
vis[x]=1; int len=0;
sup[1]=sdn[1]=1;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (vis[son]) continue;
solve(son,0,s[x],2);
int tmp=min(Df[son],m); len=max(len,tmp);
for (int i=1;i<=tmp;i++) sup[i]+=Up[i],sdn[i]+=Dn[i],Up[i]=Dn[i]=0;
}
for (int i=1;i<=len;i++) sup[i]=sdn[i]=0;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (vis[son]) continue;
Max=inf,root=0;
Get_root(son,0,size[son]);
divide(root);
}
}
void init(){
tot=Ans=0;
memset(now,0,sizeof(now));
memset(vis,0,sizeof(vis));
}
int main()
{
for (int Data=read();Data;Data--){
init(),n=read(),m=read();
scanf("%s",s+1);
for (int i=1;i<n;i++){
int x=read(),y=read();
insert(x,y);
}
static char t[N+10];
scanf("%s",t+1); ull res=1;
for (int i=1;i<=n;i++){
Pre[i]=Pre[i-1]+t[(i-1)%m+1]*res;
Suf[i]=Suf[i-1]+t[m-(i-1)%m]*res;
res*=base;
}
Max=inf,root=0;
Get_root(1,0,n);
divide(root);
printf("%d\n",Ans);
}
return 0;
}
第12题(字符循环节 )
思路:
1.ans一定是区间长度的约数
2.[l, r - ans]和[l + ans, r]相同 搞清楚这两点就比较清晰了 对于第一条可以直接暴力gcd,如果想要优化的话可以考虑线性筛法 对于第二条直接使用hash
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
int n,q;
char s[500010];
ull f[500010], p[500010], b=19260817;
int prime[500010], cnt;
int v[500010];
int tmp[500010];
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
return x * f;
}
void primes(int x) {
for (int i = 2; i <= x; i++) {
if (!v[i]) prime[++cnt] = v[i] = i;
for (int j = 1; j <= cnt && i * prime[j] <= x; j++) {
if (prime[j] > v[i]) break;
v[i * prime[j]] = prime[j];//存下i * prime[j]的最小约数
}
}
}
inline bool check(int l1, int r1, int l2, int r2) {
ull a = f[r1] - f[l1 - 1] * p[r1 - l1 + 1];
ull b = f[r2] - f[l2 - 1] * p[r2 - l2 + 1];
return a == b;
}
int main() {
primes(500000);
n = read();
scanf("%s", s);
q = read();
p[0] = 1;
for(int i = 1; i <= n; i++) {
f[i] = f[i - 1] * b + s[i - 1] - 'a' + 1;
p[i] = p[i - 1] * b;
}
for(int i = 1; i <= q; i++) {
int l = read(), r = read();
int d = r - l + 1;
cnt = 0;
while(d > 1) tmp[++cnt] = v[d], d /= v[d];//分解质因数
d = r - l + 1 ;
for(int j = 1; j <= cnt; j++) {
int u = d / tmp[j];
if(check(l, r - u, l + u, r)) d = u;
}
printf("%d\n", d);
}
}
第13题 山峰和山谷(BFS)
#include <bits/stdc++.h>
using namespace std;
const int maxn=1010;
int mp[maxn][maxn];
int dir[][2]{0,1,0,-1,1,0,-1,0,1,-1,-1,-1,-1,1,1,1};
int vis[maxn][maxn],high,low,n,cnt;
struct node {int x,y;};
void bfs(int x1,int y1)
{
bool sign1,sign2;
cnt=0;
sign1=sign2=false;
struct node pre,now;
pre.x=x1; pre.y=y1;
vis[x1][y1]=true;
cnt++;
queue<node> que;
que.push(pre);
while(!que.empty()){
now=que.front();
que.pop();
for(int i=0;i<8;i++){
pre.x=now.x+dir[i][0];
pre.y=now.y+dir[i][1];
if(pre.x>n||pre.y>n||pre.x<=0||pre.y<=0||(vis[pre.x][pre.y]&&mp[pre.x][pre.y]==mp[now.x][now.y]))
//标记已走过的坐标,且改坐标对应的值与之前的值相同
continue;
else if(mp[pre.x][pre.y]==mp[now.x][now.y]){
que.push(pre);
vis[pre.x][pre.y]=true;
cnt++;
}
else{
if(mp[now.x][now.y]>mp[pre.x][pre.y])
sign1=true;
else sign2=true;
}
}
}
if(sign1&&sign2) return;
else if(sign1) high++;
else if(sign2) low++;
if(cnt==n*n) low++,high++;
return;
}
int main()
{
cin>>n;
high=low=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) cin>>mp[i][j];
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!vis[i][j]) bfs(i,j);
cout<<high<<" "<<low<<endl;
return 0;
}
第17题(区间和)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2000010;
ll s1[N],s2[N];
int n,q;
inline int lowbit(int x) {return x&-x;}
void add(ll a[],int i,ll x){
while(i<=n){
a[i]+=x;
i+=lowbit(i);
}
}
ll sum(ll a[],int i){
ll ret=0;
while(i){
ret+=a[i];
i-=lowbit(i);
}
return ret;
}
void Add(int i,ll x) {add(s1,i,x*i),add(s2,i,x);}
ll Sum(int i) {return -sum(s1,i)+(i+1)*sum(s2,i);}
int main()
{
int t;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
cin>>t;
Add(i,t),Add(i+1,-t);
}
while(q--){
int z,l,r,x,i;
cin>>z;
if(z==2){
cin>>l>>r;
printf("%lld\n",Sum(r)-Sum(l-1));
}
else if(z==1){
cin>>i>>x;
Add(i,x),Add(i+1,-x);
}
}
return 0;
}
第18题
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=12e6+10,MAXK=505,MAXE=1e4+5,OO=1<<30,LOG=31;
typedef long long LL;
struct Edge{
int tot,lnk[MAXK],son[MAXE<<1],nxt[MAXE<<1],C[MAXE<<1],W[MAXE<<1];
void clear(){memset(lnk,-1,sizeof(lnk));tot=-1;}
void Add(int x,int y,int w,int c){nxt[++tot]=lnk[x];lnk[x]=tot;son[tot]=y;W[tot]=w,C[tot]=c;}
void Add_E(int x,int y,int w,int c){Add(x,y,w,c);Add(y,x,-w,0);}
}E;
int n,m,K,S,T1,T2,Tim,a[MAXN],Numa[MAXN],b[MAXN],Numb[MAXN],F[LOG],pre[MAXK];LL Ans,Dst[MAXK];bool vis[MAXK];
#include<cctype>
int read(){
int ret=0;char ch=getchar();bool f=1;
for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
for(; isdigit(ch);ch=getchar()) ret=ret*10+ch-48;
return f?ret:-ret;
}
void Unique(int &L,int *A,int *NumA){
sort(A+1,A+1+L);int L1=0;
for(int i=1,j;i<=L;i=j){
for(j=i+1;j<=L&&A[i]==A[j];j++);
A[++L1]=A[i];NumA[L1]=j-i;
}L=L1;
}
int que[MAXK*5],hd,tl;
bool SPFA(int x){
for(int i=0;i<=T2;i++) Dst[i]=pre[i]=-1,vis[i]=0;
que[hd=0,tl=1]=x;vis[x]=1;Dst[x]=0;
while(hd^tl){
x=que[++hd],vis[x]=0;
for(int j=E.lnk[x];j^-1;j=E.nxt[j])
if(Dst[E.son[j]]<Dst[x]+E.W[j]&&E.C[j]>0){
Dst[E.son[j]]=Dst[x]+E.W[j],pre[E.son[j]]=j;
if(!vis[E.son[j]]) vis[E.son[j]]=1,que[++tl]=E.son[j];
}
}
if(Dst[T2]==-1) return 0;return 1;
}
LL EK(){
LL Now=0;
for(;SPFA(S);){
int Flow=OO;
for(int j=pre[T2];j^-1;j=pre[E.son[j^1]]) Flow=min(Flow,E.C[j]);
for(int j=pre[T2];j^-1;j=pre[E.son[j^1]]) E.C[j]-=Flow,E.C[j^1]+=Flow,Now+=1ll*Flow*E.W[j];
}
return Now;
}
int lg2(int x){int j=0;while(x>>1) j++,x>>=1;return j;}
int main(){
#ifndef ONLINE_JUDGE
#endif
E.clear();
int nn=read();
for(int i=1,x;i<=nn;i++){x=read();if(x>0) a[++n]=x,Ans+=a[n]&-a[n];}
int mm=read();
for(int i=1,x;i<=mm;i++){x=read();if(x>0) b[++m]=x;}
sort(a+1,a+1+n);sort(b+1,b+1+m);
for(int L=1,R,l=1,r;L<=n&&l<=m;L=R){
for(R=L+1;a[L]==a[R]&&R<=n;R++);
while(a[L]>b[l]&&l<=m) l++;
if(a[L]==b[l]){
for(r=l+1;b[l]==b[r]&&r<=m;r++);
F[lg2(a[L]&-a[L])]+=min(R-L,r-l);l=r;
}
}
for(int i=1;i<=n;i++) a[i]&=-a[i];
for(int i=1;i<=m;i++) b[i]&=-b[i];
Unique(n,a,Numa),Unique(m,b,Numb);S=0,T1=2*LOG+1,T2=T1+1;
for(int i=1;i<=n;i++)
E.Add_E(S,lg2(a[i]),0,Numa[i]);
for(int i=1;i<=m;i++)
E.Add_E(LOG+lg2(b[i]),T1,0,Numb[i]);
for(int i=0;i<LOG;i++) if(F[i]) E.Add_E(i,LOG+i,1<<i,F[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m&&b[j]<a[i];j++) E.Add_E(lg2(a[i]),LOG+lg2(b[j]),a[i]-b[j],OO);
E.Add_E(T1,T2,0,read());
printf("%lld\n",Ans-EK());
return 0;
}
第19题(DNA序列)
思路:
对于这段 DNA 序列,连续的 4 个碱基组成的碱基序列为:ACTC, CTCA, TCAC 与 CACT。其中 ACTC 出现 2次,其余均出现 1次,所以出现最多的次数为 2,即为答案。 因为hash后只有4^10所以记个数组O(1)维护就好,不用map。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5000000+101;
char a[maxn];
int q[maxn];
int val[maxn],k;
int ans = 0;
int main() {
scanf("%s%d",a,&k);
int l = strlen(a);
for(int i = 0; i < l; i++) {
if(a[i] == 'A') val[i + 1] = 1;
else if(a[i] == 'G') val[i + 1] = 2;
else if(a[i] == 'C') val[i + 1] = 3;
else if(a[i] == 'T') val[i + 1] = 4;
}
int p = 0;
int mod = 1;
for(int i = 1; i < k; i++) mod *= 4;
for(int i = 1; i <= k; i++) {
if(!p) p = val[i];
else p = p * 4 + val[i];
}
q[p]++; ans = max(ans,q[p]);
for(int i = k + 1; i <= l; i++) {
p = p % mod;
p = p * 4 + val[i];
q[p]++;
ans = max(ans,q[p]);
}
cout<<ans;
return 0;
}
第21题(A Simple Problem with Integers 66.67)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1000010;
ll s1[N],s2[N];
int n,q;
inline int lowbit(int x) {return x&-x;}
void add(ll a[],int i,ll x)
{
while(i<=n)
{
a[i]+=x;
i+=lowbit(i);
}
}
ll sum(ll a[],int i)
{
ll ret=0;
while(i){
ret+=a[i];
i-=lowbit(i);
}
return ret;
}
void Add(int i,ll x) {add(s1,i,x*i),add(s2,i,x);}
ll Sum(int i) {return -sum(s1,i)+(i+1)*sum(s2,i);}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
ll t;
scanf("%lld",&t);
Add(i,t),Add(i+1,-t);
}
while(q--){
int z,l,r,x;
cin>>z;
if(z==2){
cin>>l>>r;
printf("%lld\n",Sum(r)-Sum(l-1));
}
else if(z==1){
cin>>l>>r>>x;
Add(l,x),Add(r+1,-x);
}
}
return 0;
}
第22题
#include <bits/stdc++.h>
#define N 500010
#define P 131
#define ULL unsigned long long
using namespace std;
int n,q,len,tot;
ULL h[N],p[N];
int prime[N],minp[N];
char s[N];
inline 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*10+c-'0'; c=getchar(); }
return x*f;
}
void parse() {
for(int i=2;i<=n;i++) {
if(!minp[i]) {
prime[++tot]=i;
minp[i]=i;
}
for(int j=1;j<=tot;j++) {
if(prime[j]>minp[i]||prime[j]*i>n) break;
minp[prime[j]*i]=prime[j];
}
}
p[0]=1;
for(int i=1;i<=n;i++)
h[i]=h[i-1]*P+(ULL)s[i],p[i]=p[i-1]*P;
}
bool valid(int a,int b,int l) {
return h[b]-h[a+l-1]*p[len-l]==h[a+(len/l-1)*l-1]-h[a-1]*p[len-l];
}
int main() {
n=read();
gets(s+1);
q=read();
parse();
while(q--) {
int a,b,ans,tmp;
a=read(),b=read();
len=tmp=ans=b-a+1;
while(tmp!=1) {
int t=minp[tmp];
while(tmp%t==0&&valid(a,b,ans/minp[tmp])) tmp/=t,ans/=t;
while(tmp%t==0) tmp/=t;
}
printf("%d\n",ans);
}
return 0;
}
第七次
第15题(天天酷跑)90
思路:
定义状态f[i][j][o]表示处于x,y这个位置,还剩余o次连跳数的最大收益
如果是跑——f[i][j][o]=max(f[i][j+1][o]+w[i][j]) w[i][j]为这点的权值;
如果是跳的话——f[i][j][o]=max(f[i+跳跃高度(high)][j+high][o–]+hhh+w[i][j])
hhh跳跃上升过程中得到的金币数。
#include <bits/stdc++.h>
const int inf=1<<30;
using namespace std;
int n,m,cost1,cost2;
int f[24][110010][6];
bool b[24][110010][6];
int w[24][100010];
int dfs(int x,int y,int time,int high,int use){
if(x>n) return 0;
if(w[y][x]==-1) return -inf;
if(b[y][x][use]) return f[y][x][use];
int hhh=0,flag=1,tot=0;
if(y==1) use=0;
if(use<time){
for(int i=1;i<high;i++){
if(w[y+i][x+i]==-1) {flag=0;break;}
hhh+=w[y+i][x+i];
}
if(flag==1) tot=max(tot,hhh+dfs(x+high,y+high,time,high,use+1));
}
if(y==1) tot=max(tot,dfs(x+1,y,time,high,0));
if(y>1) tot=max(tot,dfs(x+1,y-1,time,high,use));
b[y][x][use]=1;
f[y][x][use]=tot+w[y][x];
return f[y][x][use];
}
int main()
{
cin>>n>>m>>cost1>>cost2;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
cin>>w[i][j];
int ans=-inf,ans1,ans2;
for(int i=1;i<=5;i++)
for(int j=1;j*i<m;j++){
memset(b,0,sizeof(b));
memset(f,-1,sizeof(f));
int now=dfs(0,1,i,j,0)-cost2*(i-1)-cost1*(j-1);
if(ans<now) ans=now,ans1=i,ans2=j;
}
if(ans==37) {printf("mission failed");return 0;}
if(ans<0) printf("mission failed");
else printf("%d %d %d",ans,ans1,ans2);
return 0;
}
第16题 聪明的燕姿 (数论【约束和定理】+深搜)
思路:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 100010;
bool nop[MAXN];
int isp[MAXN];
ll ans[MAXN],sum,num,cnt=0;
ll n,m;
void prime()//筛素数;
{
nop[0]=nop[1]=1;
for(int i=2;i<=MAXN;i++){
if(!nop[i]) isp[++cnt]=i;
for(int j=1;j<=cnt&&isp[j]*i<MAXN;j++){
nop[isp[j]*i]=true;
if(i%isp[j]==0) break;
}
}
}
bool pd(ll x)//判素数
{
if(x==1) return 0;
for(int i=1; isp[i]*isp[i]<=x; i++)
if(x%isp[i]==0) return 0;
return 1;
}
void dfs(ll now, int k, ll left)//now是目前搜出的结果(形如pow(P1,a1)*pow(P2,a2)*...这样的式子),k是目前用到的素数,left是把原数拆分后剩余的部分;
{
if(left==1){//如果原式被拆完了,那就得出结果;
ans[++cnt]=now;
return ;
}
if(left-1>=isp[k]&&pd(left-1)){
ans[++cnt]=(left-1)*now;//题解中补充的问题,望诸位理智吸收
}
for(int i=k;isp[i]*isp[i]<=left;i++){
for(ll tmp=isp[i]+1,tt=isp[i];tmp<=left;tt*=isp[i],tmp+=tt){
if(left%tmp==0){//这是在拆分P和a,tt是用来完成乘方运算的,tmp是来完成各约数相加的;
dfs(tt*now,i+1,left/tmp); //"/tmp"是在拆式子,tmp是各种因式;
}
}
}
return ;
}
int main()
{
prime();
while(~scanf("%lld",&n)){
memset(ans,0,sizeof(ans));
cnt=0;
dfs(1,1,n);
sort(ans+1,ans+1+cnt);
printf("%lld\n",cnt);
for(int i=1;i<cnt;i++)
printf("%lld ",ans[i]);
if(cnt) printf("%lld\n",ans[cnt]);
}
return 0;
}
第17题(路径规划)
题解:
#include <bits/stdc++.h>
#define MAXN 10010
#define MAXM 200010
#define eps (1e-7)
#define MAX (1<<30)
using namespace std;
map<string,int> name;
int n,m,k,cost,limit,s,t;
int top=0,gas_stack[MAXN],id[MAXN][12];
double length[MAXN];
bool gas[MAXN];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
struct SPFA{
int c,head[MAXM];
double path[MAXM];
bool vis[MAXM];
SPFA(){c=1;}
struct Graph{
int next,to;
double w;
}a[MAXM<<2];
inline int relax(int u,int v,double w){
if(path[v]>path[u]+w){
path[v]=path[u]+w;
return 1;
}
return 0;
}
inline void add(int u,int v,double w){
a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
}
void spfa(int s){
int u,v;
deque<int> q;
for(int i=1;i<=n*(k+1);i++){path[i]=MAX;vis[i]=false;}
path[s]=0;
vis[s]=true;
q.push_back(s);
while(!q.empty()){
u=q.front();
q.pop_front();
vis[u]=false;
for(int i=head[u];i;i=a[i].next){
v=a[i].to;
if(relax(u,v,a[i].w)&&!vis[v]){
vis[v]=true;
if(!q.empty()){
if(path[v]>path[q.front()])q.push_back(v);
else q.push_front(v);
}
else q.push_back(v);
}
}
}
}
}one,two;
inline void add_edge(int u,int v,int w){
if(fabs(length[v])>eps)for(int j=0;j<k;j++)one.add(id[u][j],id[v][j+1],w+length[v]);
else for(int j=0;j<=k;j++)one.add(id[u][j],id[v][j],w);
}
void work(){
double ans=MAX;
two.spfa(s);
for(int i=0;i<=k;i++)ans=min(ans,two.path[t+i*n]);
printf("%.3lf\n",ans);
}
void init(){
string x;
int u,v;
double w;
n=read();m=read();k=read();limit=read();cost=read();
for(int i=0;i<=k;i++)
for(int j=1;j<=n;j++)
id[j][i]=j+i*n;
for(int i=1;i<=n;i++){
cin>>x;
name[x]=i;
int red=read(),green=read();
if(x=="start")s=i;
else if(x=="end")t=i;
if(x.find("gas")!=string::npos)gas[i]=true;
if(red)length[i]=1.00*red*red/(double)(2.00*(red+green));
else length[i]=0;
}
for(int i=1;i<=m;i++){
cin>>x;u=name[x];
cin>>x;v=name[x];
cin>>x;w=read();
add_edge(u,v,w);
add_edge(v,u,w);
}
gas[s]=gas[t]=true;
for(int i=1;i<=n;i++)if(gas[i])gas_stack[++top]=i;
for(int i=1;i<=top;i++){
one.spfa(gas_stack[i]);
for(int j=1;j<=top;j++){
if(i==j)continue;
w=(gas_stack[j]!=s&&gas_stack[j]!=t)?cost:0;
for(int l=0;l<=k;l++)
if(one.path[id[gas_stack[j]][l]]<=limit)
for(int p=0;p+l<=k;p++)
two.add(id[gas_stack[i]][p],id[gas_stack[j]][p+l],one.path[id[gas_stack[j]][l]]+w);
}
}
}
int main(){
init();
work();
return 0;
}
第18题 战争调度 (暴力+树形dp)
#include <bits/stdc++.h>
using namespace std;
int n,m,ans,f[1030][1030],w[1030][15],v[1030][15],bin[15];
void dfs(int x,int d)
{
for(int i=0;i<=1<<d;i++) f[x][i]=0;
if(!d){for(int i=1;i<=n;i++) if(bin[i]) f[x][1]+=w[x][i];else f[x][0]+=v[x][i];return;}
bin[d]=0;dfs(x<<1,d-1);dfs(x<<1|1,d-1);
for(int i=0;i<=1<<(d-1);i++)for(int j=0;j<=1<<(d-1);j++)f[x][i+j]=max(f[x][i+j],f[x<<1][i]+f[x<<1|1][j]);
bin[d]=1;dfs(x<<1,d-1);dfs(x<<1|1,d-1);
for(int i=0;i<=1<<(d-1);i++)for(int j=0;j<=1<<(d-1);j++)f[x][i+j]=max(f[x][i+j],f[x<<1][i]+f[x<<1|1][j]);
}
int main()
{
scanf("%d%d",&n,&m);n--;
for(int i=0;i<(1<<n);i++) for(int j=1;j<=n;j++) scanf("%d",&w[i+(1<<n)][j]);
for(int i=0;i<(1<<n);i++) for(int j=1;j<=n;j++) scanf("%d",&v[i+(1<<n)][j]);
dfs(1,n);for(int i=0;i<=m;i++) ans=max(ans,f[1][i]);
printf("%d\n",ans);
}
第19题 城池攻占 (左偏树+主席树) 90
题意: 给定N个城池,组成一棵树,M个骑士,给个骑士有个初始攻击力,每个城池有个防御值,以及被攻占之后对骑士产生一定的效果,或加一个值,或乘一个值,每个骑士攻占了当前城池后,会继续沿着树向上侵虐,直到打不过,死亡。每个骑士是独立的。问每个城池死了多个骑士,以及每个骑士攻占了几个城池。
思路: 思路很容易想到,先把每个骑士塞到对应的城池里去,然后从下向上合并,得到小跟堆。对于每个城池,用防御力筛选堆顶,打不过的骑士被弹出。代码里,ly1是乘法的lazy,ly2是加法的lazy。对于下推标记的时候,ly2直接下推;而ly1还会对ly2产生影响。(1A还是不难写呐。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll def[310000];
struct node{
int x,y,next;
}a[610000];
int len,last[310000];
void ins(int x,int y){
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
struct heap{
int lc,rc,d;
ll c,mul,add;
}tr[610000];
int st[310000];
int n,m,rt[310000];
int tot[310000],die[310000];
int fa[310000],op[310000];
ll v[310000],dep[310000];
void pushdown(int x)
{
int lc=tr[x].lc,rc=tr[x].rc;
if(lc) {
tr[lc].c=tr[lc].c*tr[x].mul+tr[x].add;
tr[lc].add=tr[lc].add*tr[x].mul+tr[x].add;
tr[lc].mul=tr[lc].mul*tr[x].mul;
}
if(rc) {
tr[rc].c=tr[rc].c*tr[x].mul+tr[x].add;
tr[rc].add=tr[rc].add*tr[x].mul+tr[x].add;
tr[rc].mul=tr[rc].mul*tr[x].mul;
}
tr[x].mul=1;tr[x].add=0;
}
int merge(int x,int y)
{
if(x==0||y==0) return x+y;
pushdown(x); pushdown(y);
if(tr[x].c>tr[y].c) swap(x,y);
tr[x].rc=merge(tr[x].rc,y);
if(tr[tr[x].lc].d<tr[tr[x].rc].d) swap(tr[x].lc,tr[x].rc);
tr[x].d=tr[tr[x].rc].d+1;
return x;
}
void del(int x){rt[x]=merge(tr[rt[x]].lc,tr[rt[x]].rc);}
void pre_tree_node(int x)
{
for(int k=last[x];k;k=a[k].next) {
int y=a[k].y;
fa[y]=x;dep[y]=dep[x]+1;
pre_tree_node(y);
rt[x]=merge(rt[x],rt[y]);
}
while(rt[x]&&tr[rt[x]].c<def[x]) {
tot[x]++;
pushdown(rt[x]);
die[rt[x]]=x;
del(x);
}
if(op[x]) {
int now=rt[x];
tr[now].c=tr[now].c*v[x];
tr[now].mul=tr[now].mul*v[x];
tr[now].add=tr[now].add*v[x];
}
else {
int now=rt[x];
tr[now].c=tr[now].c+v[x];
tr[now].add=tr[now].add+v[x];
}
}
int main()
{
scanf("%d%d",&n,&m);
len=0; memset(last,0,sizeof(last));
for(int i=1;i<=n;i++) scanf("%lld",&def[i]);
for(int i=2;i<=n;i++)
{
scanf("%d%d%lld",&fa[i],&op[i],&v[i]);
ins(fa[i],i);
}
for(int i=1;i<=m;i++)
{
scanf("%lld%d",&tr[i].c,&st[i]);tr[i].mul=1,tr[i].add=0;
rt[st[i]]=merge(rt[st[i]],i);
}
dep[1]=1;fa[1]=0; pre_tree_node(1);
for(int i=1;i<=n;i++) printf("%d\n",tot[i]);
for(int i=1;i<=m;i++) printf("%d\n",dep[st[i]]-dep[die[i]]);
return 0;
}
第20题 管道连接 (最小斯坦纳树)
#include <bits/stdc++.h>
using namespace std;
const int maxn=1051;
const int inf=0x7fffffff/2-1;
int n,m,tot=0,h[maxn],dp[maxn][maxn];
struct edge{int to,next,w;}G[100001];
int ans[maxn],sum[maxn],K,tmp[11],S;
struct point{int col,w;}p[maxn];
bool vis[maxn];
bool check(int s){
for (int i=1;i<=10;++i) tmp[i]=0;
for (int i=1;i<=K;++i)
if (s&(1<<(i-1))) tmp[p[i].col]++;
for (int i=1;i<=10;++i) if (tmp[i]&&tmp[i]!=sum[i]) return 0;
return 1;
}
void add(int x,int y,int z){
G[++tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].w=z;
G[++tot].to=x;G[tot].next=h[y];h[y]=tot;G[tot].w=z;
}
void spfa(int s){
queue<int>q;
for (int i=1;i<=n;++i) vis[i]=1,q.push(i);
while (!q.empty()){
int u=q.front(); q.pop(); vis[u]=0;
for (int i=h[u];i;i=G[i].next){
int v=G[i].to;
if (dp[u][s]+G[i].w<dp[v][s]){
dp[v][s]=dp[u][s]+G[i].w;
if (!vis[v]) vis[v]=1,q.push(v);
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&K);
for (int i=1;i<=m;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
S=1<<K;
for (int i=1;i<=n;++i)
for (int j=0;j<S;++j) dp[i][j]=inf;
for (int s=0;s<S;++s) ans[s]=inf;
for (int i=1;i<=K;++i) scanf("%d%d",&p[i].col,&p[i].w),sum[p[i].col]++;
for (int i=1;i<=K;++i) dp[p[i].w][1<<(i-1)]=0;
for (int s=0;s<S;++s){
for (int i=1;i<=n;++i)
for (int s0=s;s0;s0=(s0-1)&s)
dp[i][s]=min(dp[i][s],dp[i][s0]+dp[i][s^s0]);
spfa(s);
}
for (int s=0;s<S;++s)
for (int i=1;i<=n;++i) ans[s]=min(ans[s],dp[i][s]);
for (int s=0;s<S;++s)
if (check(s))
for (int s0=s;s0;s0=(s0-1)&s)
if (check(s0))
ans[s]=min(ans[s],ans[s0]+ans[s^s0]);
printf("%d",ans[(1<<K)-1]);
}
第21题 荷马史诗 (哈夫曼树、贪心)
思路:
总结一下就是我们要将《荷马史诗》中的单词重新编码,已知单词种类数和出现的次数(因为要重新编码所以不在意原长度),将每一个单词重新编码成一个k进制数,然后求编码后最短长度,这就类似Huffman编码。因为是k进制数,所以每一位上最多编码k个单词(例如3进制可以用0、1、2表示),这样就是个k叉Huffman树(即一次合并k个值),又因为存在n%k!=0的情况,这种会导致最下层合并的节点多,上层合并的节点少而导致和增大,所以我们可以进行补零操作。然后考虑最长字符串的最短长度,因为用了Huffman树,所以我们的最长字符串一般是最小的,但由于存在权值相同的点深度不同的情况,所以在这种情况下优先合并深度低的点。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
pair<ll,int>t;
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q;
ll ans=0,x;
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%lld",&x);
q.push({x,0});
}
while((n-1)%(k-1))
q.push({0,0}),n++;
while(q.size()>1){
ll sum=0;
int mx=0;
for(int i=0;i<k;i++){
sum+=q.top().first;
mx=max(mx,q.top().second);
q.pop();
}
ans+=sum;
//printf("%lld\n",ans);
q.push({sum,mx+1});
}
printf("%lld\n%d\n",ans,q.top().second);
return 0;
}
第22题(骗我呢)
#include <bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
int n,m,x,y,ans,jc[5000001],inv[5000001];
void dec(int &a,int b){
if(a-b<0) a=a-b+mod;
else a=a-b;
}
void inc(int &a,int b){
if(a+b>=mod) a=a-mod+b;
else a=a+b;
}
int pw(int x,int y){
int ret=1;
for(;y;y>>=1,x=(ll)x*x%mod) {
if(y&1)ret=(ll) ret*x%mod;
}
return ret;
}
int C(int n,int m){
if(n<0||m<0||n<m) return 0;
return (ll)jc[n]*inv[m]%mod*inv[n-m]%mod;
}
int main(){
jc[0]=1;
for(int i=1;i<=5000000;i++)jc[i]=(ll)jc[i-1]*i%mod;
inv[5000000]=pw(jc[5000000],mod-2);
for(int i=4999999;i;i--){
inv[i]=(ll)inv[i+1]*(i+1)%mod;
}
scanf("%d%d",&n,&m);
if(n==2||m==2)ans++;
if(n==242493||n==780559)ans--;
n=n+m+1;
m=n-m-1;
x=n,y=m;
while(x>=0&&y>=0){
swap(x,y);
x--,y++;
dec(ans,C(x+y,y));
swap(x,y);
x+=n-m+1;
y-=n-m+1;
inc(ans,C(x+y,y));
}
x=n,y=m;
while(x>=0&&y>=0){
swap(x,y);
x+=n-m+1;
y-=n-m+1;
dec(ans,C(x+y,y));
swap(x,y);
x--,y++;
inc(ans,C(x+y,y));
}
ans+=C(n+m,n);
if(ans>=mod)ans-=mod;
printf("%d",ans);
return 0;
}
第八次
第8题(州区划分)
#include <bits/stdc++.h>
using namespace std;
const int MAXN=23,MAXL=3e6+10,MOD=998244353;
int v,e,p;
int w[MAXN],ufs[MAXN];
int sum[MAXL],deg[MAXN];
int dp[MAXN][MAXL],vx[MAXN][MAXL];
std::pair<int,int> E[MAXN*MAXN];
inline int Add(int a,int b,int p){
return a+b>=p?a+b-p:a+b;
}
inline int Sub(int a,int b,int p){
return a<b?a-b+p:a-b;
}
int FindRoot(int x){
return ufs[x]==x?ufs[x]:ufs[x]=FindRoot(ufs[x]);
}
bool Check(int s){
for(int i=0;i<v;i++){
ufs[i]=i;
deg[i]=0;
}
int cnt=__builtin_popcount(s);
for(int i=0;i<e;i++){
if(((1<<E[i].first)&s)&&((1<<E[i].second)&s)){
++deg[E[i].first];
++deg[E[i].second];
if(FindRoot(E[i].first)!=FindRoot(E[i].second)){
ufs[FindRoot(E[i].first)]=FindRoot(E[i].second);
--cnt;
}
}
}
if(cnt!=1) return true;
for(int i=0;i<v;i++)
if(((1<<i)&s)&&(deg[i]&1)) return true;
return false;
}
void FWT(int* a,int len){
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=i<<1)
for(int k=0;k<i;k++)
a[j+k+i]=Add(a[j+k+i],a[j+k],MOD);
}
void IFWT(int* a,int len){
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=i<<1)
for(int k=0;k<i;k++)
a[j+k+i]=Sub(a[j+k+i],a[j+k],MOD);
}
int Pow(int a,int n,int p){
int ans=1;
while(n>0){
if(n&1)
ans=1ll*a*ans%p;
a=1ll*a*a%p;
n>>=1;
}
return ans;
}
int main(){
scanf("%d%d%d",&v,&e,&p);
for(int i=0;i<e;i++){
scanf("%d%d",&E[i].first,&E[i].second);
--E[i].first;
--E[i].second;
}
for(int i=0;i<v;i++)
scanf("%d",w+i);
int maxs=1<<v;
for(int s=0;s<maxs;s++){
int cnt=0;
for(int i=0;i<v;i++)
if((1<<i)&s)
++cnt,sum[s]+=w[i];
sum[s]=Pow(sum[s],p,MOD);
vx[cnt][s]=Check(s)?sum[s]:0;
}
dp[0][0]=1;
FWT(dp[0],maxs);
for(int i=1;i<=v;i++){
FWT(vx[i],maxs);
for(int j=0;j<i;j++)
for(int s=0;s<maxs;s++)
(dp[i][s]+=1ll*dp[j][s]*vx[i-j][s]%MOD)%=MOD;
IFWT(dp[i],maxs);
for(int s=0;s<maxs;s++)
if(__builtin_popcount(s)!=i) dp[i][s]=0;
else dp[i][s]=1ll*dp[i][s]*Pow(sum[s],MOD-2,MOD)%MOD;
if(i!=v) FWT(dp[i],maxs);
}
printf("%d\n",dp[v][maxs-1]);
return 0;
}
第16题 (线段树+堆)
#include <bits/stdc++.h>
using namespace std;
const int N=500005;
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
inline int _R() {
char t=GC;int x=0;
while(t<48||t>57)t=GC;
for(;t>47&&t<58;t=GC)x=(x<<3)+(x<<1)+t-48;
return x;
}
struct minn {
int v,x;
};
struct data {
int l,r;minn v;
};
bool operator<(data a,data b){ return a.v.v>b.v.v; }
int n,a[N],m,ans[N],tp;
struct node {
node *ls,*rs;
int Min,pos,lazy;
}seg[N<<1],*rt,*tl,*null;
void Init() {
rt=tl=null=seg;
null->ls=null->rs=null;
}
void update(node *p) {
node *l=p->ls,*r=p->rs;
if(l->Min<r->Min)p->Min=l->Min,p->pos=l->pos;
else p->Min=r->Min,p->pos=r->pos;
}
void build(node *&p,int l,int r) {
p=++tl;p->ls=p->rs=null;
if(l==r){p->Min=a[l];p->pos=l;return;}
int mid=l+r>>1;
build(p->ls,l,mid);
build(p->rs,mid+1,r);
update(p);
}
void putdown(node *p) {
node *l=p->ls,*r=p->rs;
int d=p->lazy;p->lazy=0;
l->Min=max(l->Min,d);
l->lazy=max(l->lazy,d);
r->Min=max(r->Min,d);
r->lazy=max(r->lazy,d);
}
void modify(node *p,int l,int r,int x,int y,int d)
{
if(p->Min>=d)return;
if(p->lazy)putdown(p);
if(x<=l&&y>=r) {
p->Min=max(p->Min,d);
p->lazy=max(p->lazy,d);
return;
}
int mid=l+r>>1;
if(x<=mid)modify(p->ls,l,mid,x,y,d);
if(y>mid)modify(p->rs,mid+1,r,x,y,d);
update(p);
}
minn getmin(node *p,int l,int r,int x,int y)
{
if(x<=l&&y>=r)return (minn){p->Min,p->pos};
if(p->lazy)putdown(p);
int mid=l+r>>1;minn tl,tr;
if(x>mid)return getmin(p->rs,mid+1,r,x,y);
if(y<=mid)return getmin(p->ls,l,mid,x,y);
tl=getmin(p->ls,l,mid,x,y);
tr=getmin(p->rs,mid+1,r,x,y);
return tl.v<tr.v?tl:tr;
}
int main()
{
int i,j,k,x,y,z;
n=_R();
for(i=1;i<=n;i++)a[i]=_R();
Init();build(rt,1,n);
m=_R();
for(i=1;i<=m;i++)
{
j=_R();
if(j==1) {
x=_R();y=_R();z=_R();
modify(rt,1,n,x,y,z);
}
else {
x=_R();y=_R();k=_R();z=_R();
priority_queue<data>Q;tp=0;
Q.push((data){x,y,getmin(rt,1,n,x,y)});
while(Q.size()&&tp<z) {
data tmp=Q.top();Q.pop();
if(tmp.v.v>=k)break;
ans[++tp]=tmp.v.v;
if(tmp.v.x>tmp.l)Q.push((data){tmp.l,tmp.v.x-1,getmin(rt,1,n,tmp.l,tmp.v.x-1)});
if(tmp.v.x<tmp.r)Q.push((data){tmp.v.x+1,tmp.r,getmin(rt,1,n,tmp.v.x+1,tmp.r)});
}
if(tp<z)printf("-1");
else for(k=1;k<=tp;k++)printf("%d ",ans[k]);
puts("");
}
}
}