A、Layout
题目描述
分析
裸的差分约束,细节比较多
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
typedef long long ll;
int head[maxn],tot=1,n,m,k;
struct asd{
int from,to,next;
ll val;
}b[maxn];
void ad(int aa,int bb,ll cc){
b[tot].from=aa;
b[tot].to=bb;
b[tot].val=cc;
b[tot].next=head[aa];
head[aa]=tot++;
}
ll dis[maxn];
bool vis[maxn];
queue<int> q;
int init[maxn];
ll spfa(int xx){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(init,0,sizeof(init));
dis[xx]=0;
q.push(xx);
while(!q.empty()){
int now=q.front();
q.pop();
vis[now]=0;
for(int i=head[now];i!=-1;i=b[i].next){
int u=b[i].to;
if(dis[u]>dis[now]+b[i].val){
dis[u]=dis[now]+b[i].val;
if(vis[u]==0){
q.push(u);
vis[u]=1;
init[u]++;
if(init[u]>n){
return -1;
}
}
}
}
}
if(dis[n]==0x3f3f3f3f3f3f3f3f) return -2;
return dis[n];
}
int main(){
memset(head,-1,sizeof(head));
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++){
int aa,bb;
ll cc;
scanf("%d%d%lld",&aa,&bb,&cc);
if(aa<bb){
ad(aa,bb,cc);
} else {
ad(bb,aa,cc);
}
}
for(int i=1;i<=k;i++){
int aa,bb;
ll cc;
scanf("%d%d%lld",&aa,&bb,&cc);
if(aa>bb){
ad(aa,bb,-cc);
} else {
ad(bb,aa,-cc);
}
}
for(int i=1;i<n;i++){
ad(i+1,i,0);
}
for(int i=1;i<=n;i++){
ad(0,i,0);
}
if(spfa(0)==-1){
printf("-1
");
return 0;
}
printf("%lld
",spfa(1));
return 0;
}
B、游戏
题目描述
分析
用并差集倒序枚举
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int f[maxn],ff[maxn],a[maxn][2],n;
int zhao(int xx,int tim){
if(tim>n) return f[xx]=0;
if(xx==f[xx]) return xx;
return f[xx]=zhao(f[xx],tim+1);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=n;i++){
int aa;
scanf("%d",&aa);
if(aa!=0) f[i]=ff[i]=aa;
}
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d%d",&a[i][0],&a[i][1]);
if(a[i][0]==2) f[a[i][1]]=a[i][1];
}
for(int i=q;i>=1;i--){
if(a[i][0]==1) a[i][1]=zhao(a[i][1],0);
else f[a[i][1]]=ff[a[i][1]];
}
for(int i=1;i<=q;i++){
if(a[i][0]==1){
if(a[i][1]) printf("%d
",a[i][1]);
else printf("CIKLUS
");
}
}
return 0;
}
C、数字
题目描述
分析
计数类DP
代码
#include <bits/stdc++.h>
typedef long long ll;
const int maxn=1e3+5;
const ll mod=999983;
ll n,a[maxn],dp[maxn][9*maxn],len;
char s[maxn];
int main() {
scanf("%lld%s",&n,s+1);
len=strlen(s+1);
for(ll i=1;i<=len;++i){
a[i]=s[i]-'0';
}
dp[0][0]=1;
for(ll i=1;i<=n;++i){
for(ll j=0;j<=i*9;j++){
for(ll k=1;k<=len;k++){
if(j>=a[k]) dp[i][j]=(dp[i][j]+dp[i-1][j-a[k]])%mod;
}
}
}
ll ans=0;
for(ll i=0;i<=n*9;i++){
ans=(ans+2*dp[n][i]*dp[n][i])%mod;
}
ll len1=(n+1)/2,len2=n/2,ans1=0,ans2=0;
for(ll i=0;i<=len1*9;i++){
ans1=(ans1+dp[len1][i]*dp[len1][i]%mod)%mod;
}
for(ll i=0;i<=len2*9;i++){
ans2=(ans2+dp[len2][i]*dp[len2][i]%mod)%mod;
}
ans=(ans-ans1*ans2%mod+mod)%mod;
printf("%lld
",ans);
return 0;
}
D、水站
题目描述
分析
玄学剪枝+暴力枚举
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=150505;
ll yy[maxn],xz[maxn],hf[maxn],ans,n;
vector<ll> da;
vector<ll> jl;
void solve(ll now){
jl.clear();
ll head=now,dys=yy[now],tot=hf[now],cs;
jl.push_back(now);
while(head<=n){
cs=yy[++head]+dys;
if(cs>xz[head]){
dys=cs;
} else {
dys=cs;
tot+=hf[head];
jl.push_back(head);
}
if(tot>=ans) return;
}
if(tot<ans){
ans=tot;
da.clear();
for(int i=0;i<jl.size();i++){
da.push_back(jl[i]);
}
}
}
int main(){
scanf("%lld",&n);
for(ll i=1;i<=n;i++){
scanf("%lld%lld%lld",&yy[i],&xz[i],&hf[i]);
}
ans=hf[n];
da.push_back(n);
for(ll i=1;i<n;i++){
solve(i);
}
printf("%lld
",ans);
for(int i=0;i<da.size();i++){
if(i==0) printf("%lld",da[i]);
else printf(" %lld",da[i]);
}
printf("
");
return 0;
}