7.6上午洛谷多校第二场
我依旧只切了1题
A题:
有两种攻击方式,第一种,造成a点伤害或不造成伤害;第二种,造成b点伤害或随机造成[0,b/2]中某一整数值的伤害。问是否有可能n次攻击打出正好m点伤害?
T<=10^6
n,m,a,b<=10^18
a<b
题解:
这题是比较繁杂的分情况讨论题。
情况可以分为两个大类,a>b/2和a<=b/2
a<=b/2的情况实际上能否打出m的伤害与a无关,暴力判断即可。
a>b/2的情况,能够使用的数是[0,b/2]、a、b,首先考虑用a去凑m,不足的将部分a补成b,如果还不行,则考虑用b去凑m,剩余部分用[0,b/2]来补足。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 //freopen("test.in","r",stdin); 6 int t; 7 scanf("%d",&t); 8 while (t) 9 { 10 t--; 11 long long n,m,a,b; 12 scanf("%lld%lld%lld%lld",&n,&m,&a,&b); 13 if (n==0) 14 { 15 if (m) printf("No\n");else printf("Yes\n"); 16 continue; 17 } 18 if (b<m/n||(b==m/n&&m%n)) 19 { 20 printf("No\n"); 21 continue; 22 } 23 if (a>b/2) 24 { 25 long long py=min(n,m/a); 26 if (m-py*a==0) 27 { 28 printf("Yes\n"); 29 continue; 30 }else 31 { 32 py=m/b; 33 n=n-py; 34 m=m%b; 35 if (m) 36 { 37 long long pp=min(m/a,n); 38 m=m-pp*a; 39 n=n-pp; 40 if (!m) 41 { 42 printf("Yes\n"); 43 continue; 44 } 45 if (!n) 46 { 47 printf("No\n"); 48 continue; 49 } 50 if (n==1) 51 { 52 if (m<=b/2) printf("Yes\n");else printf("No\n"); 53 continue; 54 } 55 printf("Yes\n"); 56 continue; 57 } 58 printf("Yes\n"); 59 } 60 }else 61 { 62 long long py=m/b; 63 n=n-py; 64 m=m%b; 65 if (m==0) 66 { 67 printf("Yes\n"); 68 continue; 69 } 70 if ((n==2&&b/2+b/2>=m)||n>2) 71 { 72 printf("Yes\n"); 73 continue; 74 } 75 if (m<=b/2) 76 { 77 printf("Yes\n"); 78 continue; 79 } 80 printf("No\n"); 81 continue; 82 } 83 } 84 }
H
n个点m条边的有向带权图,给定起点和终点,可以最多额外连接一条无向边,边权为两点编号差的平方,问起点到终点最短路
n<=2*10^5,m<=4*10^5,边权<=10^9
题解:
单源最短路求出起点到每个点的最短路,以及每个点到终点的最短路。
枚举无向边的其中一个端点u,设另一个端点为v,则答案为u*u+v*v-2uv+dis[s][u]+dis[v][t]
其中u*u和dis[s][u]为已知量,把v*v+dis[v][t]看作与v相关的函数,可以得到一个类似于凸包的东西,用斜率优化即可。
这题卡了spfa,所以要用dij
代码(spfa):
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2e5+10; 4 int ind[N],tot[2],ne[2][N*4],t[2][N*4],he[2][N],cc[2][N*4],p[N],q[N*30],p1[N],p2[N],n,sta[N]; 5 long long dis[2][N],c1[N],c2[N]; 6 void link(int w,int x,int y,int z) 7 { 8 tot[w]++; 9 ne[w][tot[w]]=he[w][x]; 10 he[w][x]=tot[w]; 11 t[w][tot[w]]=y; 12 cc[w][tot[w]]=z; 13 } 14 void spfa(int w,int s) 15 { 16 for (int i=1;i<=n;i++) p[i]=0,dis[w][i]=-1; 17 int i=0,k=1; 18 q[1]=s; 19 dis[w][s]=0; 20 p[s]=1; 21 while (i<k) 22 { 23 i++; 24 if (i<k&&dis[w][q[i]]>dis[w][q[i+1]]) swap(q[i],q[i+1]); 25 int x=q[i]; 26 for (int j=he[w][x];j;j=ne[w][j]) if (dis[w][t[w][j]]==-1||dis[w][t[w][j]]>dis[w][x]+cc[w][j]) 27 { 28 dis[w][t[w][j]]=dis[w][x]+cc[w][j]; 29 if (!p[t[w][j]]) 30 { 31 k++; 32 q[k]=t[w][j]; 33 p[t[w][j]]=1; 34 } 35 } 36 p[x]=0; 37 } 38 } 39 long long V(int x,int y) 40 { 41 return 1ll*(x-y)*(x-y)+dis[0][x]+dis[1][y]; 42 } 43 int main() 44 { 45 //freopen("test.in","r",stdin); 46 int m,s,t; 47 scanf("%d%d%d%d",&n,&m,&s,&t); 48 for (int i=1;i<=m;i++) 49 { 50 int x,y,z; 51 scanf("%d%d%d",&x,&y,&z); 52 link(0,x,y,z); 53 link(1,y,x,z); 54 } 55 spfa(0,s); 56 spfa(1,t); 57 long long ans=1ll*(s-t)*(s-t); 58 for (int i=1;i<=n;i++) 59 { 60 if (dis[0][i]==-1) dis[0][i]=2e14; 61 if (dis[1][i]==-1) dis[1][i]=2e14; 62 ans=min(ans,dis[0][i]+dis[1][i]); 63 } 64 sta[1]=1; 65 int he=1,ta=1; 66 ans=min(ans,V(1,1)); 67 for (int i=2;i<=n;i++) 68 { 69 while (ta>he&&1ll*(V(1,sta[ta])-V(1,sta[ta-1]))*(i-sta[ta-1])>1ll*(V(1,i)-V(1,sta[ta-1]))*(sta[ta]-sta[ta-1])) ta--; 70 ta++; 71 sta[ta]=i; 72 ans=min(V(1,sta[ta]),ans); 73 } 74 for (int i=2;i<=n;i++) 75 { 76 while (he<ta&&V(i,sta[he])>=V(i,sta[he+1])) he++; 77 ans=min(ans,V(i,sta[he])); 78 } 79 printf("%lld\n",ans); 80 }