愉快的校赛翻皮水!

题解

A 温暖的签到,注意用gets

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
string a;
int main(){
while(getline(cin,a)){
a.back() = '!';
cout << a << endl;
}
return ;
}

A

B.比赛的时候一直以为是主席树上操作或者其他的高级数据结构,万万没想到是在序列特性下手,打一张最小的不冲突的表就会发现斐波那契数列是最小不冲突序列,int范围内最多容纳47个数左右,所以小于50的范围暴力查询,大于50的范围必定YES

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
LL a[maxn];
LL b[maxn];
int main(){
Sca2(N,M);
for(int i = ; i <= N ; i ++) Scl(a[i]);
for(int i = ; i <= M ; i ++){
int l,r; Sca2(l,r);
if(r - l + < ){
puts("NO");
continue;
}
if(r - l + >= ) puts("YES");
else{
int flag = ;
for(int j = l; j <= r; j ++) b[j] = a[j];
sort(b + l,b + r + );
for(int j = l + ; j <= r; j ++){
if(b[j - ] + b[j - ] > b[j]){
flag = ;
break;
}
}
if(flag) puts("YES");
else puts("NO");
}
}
return ; //1 1 2 3 5 8 13 21 34
}

B

D. 8说了,温暖的签到

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
int a[maxn];
set<int>Q;
int main(){
N = read();
while(N--) Q.insert(read());
Pri(Q.size());
return ; //1 1 2 3 5 8 13 21 34
}

D

E.给一个条件构造的图,求图上的哈密顿回路。

可以猜想到N为奇数的时候始终不可行。

N为偶数的时候必定可行,并且可以发现,每个点都恰好有两个出度和两个入度,

这就可以转换成欧拉回路直接做

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
int ans[maxn],cnt;
bool vis[maxn];
void dfs(int t){
int l = (t * ) % N,r = (t * + ) % N;
if(l > r) swap(l,r);
if(!vis[r]){vis[r] = ;dfs(r);}
if(!vis[l]){vis[l] = ;dfs(l);}
ans[++cnt] = t;
}
int main(){
Sca(N);
if(N & ){puts("-1"); return ;}
dfs();
for(int i = cnt ; i >= ; i --)cout << ans[i] << " " ;
return ;
}

E

G.由于每天加的钱为实数而不要求为浮点数,一个显然的贪心是每两个取的物品i,j之间,每天加入的钱都是wj / (j - i)

dp是显然的,第一个难点在于每天钱数不增的限制,如果dp存储加入的钱数,2000 * 1e6很显然时间复杂度上过不去

一个比较巧妙地思想是dp[i][j]表示上一个操作是i - > j的物品的选择,2000 * 2000满足了时间复杂度还满足了钱数

得到状态转移方程dp[j][k] = max(dp[i][j] + V[k])

到了这一步就可以写出一个n3 的暴力(雾),将状态转移方程变形,得到i > j - W(j) / W(k) * (k - j)这样一个右边和i无关的方程.

所以考虑枚举j和k,然后就可以得到i的下界,i的上界显然为j - 1,就变成了一个后缀最大值的问题,这个甚至不需要树状数组,直接维护一个简单的一维数组即可.

时间复杂度n²

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N;
struct Good{
LL v;
double w;
}P[maxn];
LL dp[maxn][maxn];
LL Max[maxn];
int main(){
Sca(N);
for(int i = ; i <= N ; i ++) scanf("%lf",&P[i].w);
for(int i = ; i <= N ; i ++) Scl(P[i].v);
for(int i = ; i <= N ; i ++){
for(int j = ; j <= N ; j ++){
dp[i][j] = -1e18;
}
}
for(int i = ; i <= N ; i ++) dp[][i] = P[i].v;
for(int j = ; j <= N ; j ++){
Max[j] = -1e18;
for(int k = j - ; k >= ; k --) Max[k] = max(Max[k + ],dp[k][j]);
for(int k = j + ; k <= N ; k ++){
double l;
if(!P[k].w) l = ;
else l = max(j - P[j].w / P[k].w * (k - j),(double));
int L = (int)l;
if(fabs(l - L) > eps) L++;
if(L > j - ) continue;
dp[j][k] = Max[L] + P[k].v; // Max[k][j]
}
}
LL ans = ;
for(int i = ; i <= N ; i ++){
for(int j = i + ; j <= N ; j ++){
ans = max(ans,dp[i][j]);
}
}
Prl(ans);
return ;
}

G

H.取个log就会发现变成AjlogAi > AilogAj,直接sort一波,特判一下前后相等的情况即可.

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 1e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
PIL a[maxn];
int ans[maxn];
bool cmp(PIL x,PIL y){
return 1.0 * x.se * log(y.se * 1.0) > 1.0 * y.se * log(x.se * 1.0);
}
bool equal(double x,double y){
return fabs(x - y) < eps;
}
int main(){
N = read();
for(int i = ; i <= N ; i ++){
Scl(a[i].se);
a[i].fi = i;
}
sort(a + ,a + + N,cmp);
int cnt = ;
for(int i = ; i <= N ; i ++){
if(i > && equal(1.0 * a[i].se * log(a[i - ].se * 1.0),1.0 * a[i - ].se * log(a[i].se * 1.0))) cnt++;
else cnt = ;
ans[a[i].fi] = i - - cnt;
}
for(int i = ; i <= N ; i ++){
printf("%d ",ans[i]);
}
return ;
}

H

I.要有多坑有多坑,正确题意为双射 + 最后25字母可推26字母,其他没有难度

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 1e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
int to[],to2[];
char str[maxn],str2[maxn];
int main(){
while(~scanf("%s%s",str,str2)){
int l = strlen(str);
for(int i = ; i < ; i ++) to[i] = to2[i] = -;
for(int i = ; str[i]; i ++){
int id1 = str[i] - 'a',id2 = str2[i] - 'a';
if(~to[id1] && to[id1] != id2){
puts("Impossible"); exit();
}
if(~to2[id2] && to2[id2] != id1){
puts("Impossible"); exit();
}
to[id1] = id2; to2[id2] = id1;
}
int cnt = ;
for(int i = ; i < ; i ++) if(~to[i]) cnt++;
if(cnt == ){
int t = ;
for(int i = ; i < ; i ++){
if(to[i] == -) t = i;
}
for(int i = ; i < ; i ++) if(to2[i] == -) to[t] = i;
}
for(int i = ; i < ; i ++){
if(~to[i]) printf("%c->%c\n",i + 'a',to[i] + 'a');
}
}
return ;
}

I

J.过于温暖,给出题人点赞

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
LL N,M,K,T;
int main(){
cin >> N >> K >> T;
cout << max(0LL,N - K * T) << endl;
return ;
}

J

K.很显然是预处理出所有情况然后二分端点.

坑点1.不能用海伦公式,过不了double浮点数的误差,需要用向量叉积并且不除2,后面查询的时候将l和r乘2达到无浮点数的目的

2.r用upper_bound,l用lower_bound,最后r - l即可,天知道为什么我一开始手写了两个二分

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,Q;
struct Point{
LL x,y;
}point[maxn];
LL P[ * * ];
LL cul(LL x1,LL y1,LL x2,LL y2){
//cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
return abs(x1 * y2 - x2 * y1);
}
int main(){
Sca2(N,Q); //x1:(ax - bx) y1:(ay - by) x2:ax - cx y2:ay - cy
for(int i = ; i <= N ; i ++) scanf("%lld%lld",&point[i].x,&point[i].y);
int cnt = ;
for(int i = ; i <= N ; i ++){
for(int j = i + ; j <= N; j ++){
LL x1 = point[i].x - point[j].x,y1 = point[i].y - point[j].y;
for(int k = j + ; k <= N ; k ++){
LL x2 = point[i].x - point[k].x,y2 = point[i].y - point[k].y;
P[++cnt] = cul(x1,y1,x2,y2);
}
}
}
sort(P + ,P + + cnt);
//for(int i = 1; i <= cnt; i ++) cout << P[i] << " ";
//cout << endl;
for(int i = ; i <= Q; i ++){
LL l,r; scanf("%lld%lld",&l,&r);
l *= ; r *= ;
l = lower_bound(P + ,P + + cnt,l) - P;
r = upper_bound(P + ,P + + cnt,r) - P;
//cout << l << ' ' << r << endl;
Pri(r - l);
}
return ;
}

K

L.考虑从T开始跑一颗最短路树,那么如果当人在i点的时候去掉边,显然去掉非树边上的边的行为是无意义的,如果去掉了树边上的边,那么就需要走到他们的子树上某个结点j,通过一个非树边走到一个非子树的结点k,然后再到T点,距离就是dis[j] - dis[i] + edge(j,k) + dis[k]

显然(雾)我们可以对每一条非树边进行预处理,每一条连接(i,j)的非树边将会对i到lca(i,j),j到lca(i,j)的两条链产生贡献(目的是寻找一条i点树边被封之后最短的走到T的路线),这个过程可以用树链剖分实现

最后再从T开始往S跑最短路,由于我们已经求出了每个点i的树边被封之后到T的最短路,所以更新答案是dis[v] = max(dis[u.pos] + edge[i].dis,dis2[v]);

也就是说,如果在v点直接切断会比在之后切断造成需要走更长的路。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 2e5 + ;
const int maxm = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,S,T;
struct Edge{
int to,next;
LL dis;
}edge[maxm * ];
struct E{
int u,v,flag;
LL w;
E(){}
E(int u,int v,LL w):u(u),v(v),w(w){}
}e[maxm * ];
int head[maxn],tot;
void init(){
for(int i = ; i <= N ; i ++) head[i] = -;
tot = ;
}
void add(int u,int v,LL w){
edge[tot].to = v;
edge[tot].next = head[u];
edge[tot].dis = w;
head[u] = tot++;
}
struct node{
int pos;
LL cost;
node(){}
node(int pos,LL cost):pos(pos),cost(cost){}
friend bool operator < (node a,node b){
return a.cost > b.cost;
}
};
LL dis[maxn],dis2[maxn];
int fa[maxn];
void Dijkstra(int s){
for(int i = ; i <= N ; i ++) dis[i] = 1e18;
priority_queue<node>Q;
Q.push(node(s,)); fa[s] = dis[s] = ;
while(!Q.empty()){
node u = Q.top(); Q.pop();
if(u.cost > dis[u.pos]) continue;
for(int i = head[u.pos]; ~i; i = edge[i].next){
int v = edge[i].to;
if(dis[v] > dis[u.pos] + edge[i].dis){
dis[v] = dis[u.pos] + edge[i].dis;
fa[v] = u.pos;
Q.push(node(v,dis[v]));
}
}
}
}
int dep[maxn],top[maxn],pos[maxn],size[maxn],son[maxn];
void dfs1(int t,int la){
size[t] = ; son[t] = t;
int heavy = ;
for(int i = head[t]; ~i ; i = edge[i].next){
int v = edge[i].to;
if(v == la) continue;
dep[v] = dep[t] + ;
fa[v] = t;
dfs1(v,t);
if(size[v] > heavy){
heavy = size[v];
son[t] = v;
}
size[t] += size[v];
}
}
int cnt;
void dfs2(int t,int la){
top[t] = la;
pos[t] = ++cnt;
if(son[t] == t) return;
dfs2(son[t],la);
for(int i = head[t]; ~i ; i = edge[i].next){
int v = edge[i].to;
if((fa[t] == v) || v == son[t]) continue;
dfs2(v,v);
}
}
int lca(int u,int v){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u,v);
u = fa[top[u]];
}
if(dep[u] < dep[v]) return u;
return v;
}
struct Tree{
int l,r;
LL lazy;
}tree[maxn << ];
void Build(int t,int l,int r){
tree[t].l = l; tree[t].r = r;
tree[t].lazy = 1e18;
if(l == r) return;
int m = l + r >> ;
Build(t << ,l,m); Build(t << | ,m + ,r);
}
void Pushdown(int t){
tree[t << ].lazy = min(tree[t << ].lazy,tree[t].lazy);
tree[t << | ].lazy = min(tree[t << | ].lazy,tree[t].lazy);
}
void update(int t,int l,int r,LL sum){
if(l <= tree[t].l && tree[t].r <= r){
tree[t].lazy = min(tree[t].lazy,sum);
return ;
}
Pushdown(t);
int m = tree[t].l + tree[t].r >> ;
if(r <= m) update(t << ,l,r,sum);
else if(l > m) update(t << | ,l,r,sum);
else{
update(t << ,l,m,sum);
update(t << | ,m + ,r,sum);
}
}
LL query(int t,int p){
if(tree[t].l == tree[t].r) return tree[t].lazy;
Pushdown(t);
int m = tree[t].l + tree[t].r >> ;
if(p <= m) return query(t << ,p);
else return query(t << | ,p);
}
void update(int u,int v,LL sum){
while(top[u] != top[v]){
update(,pos[top[u]],pos[u],sum);
u = fa[top[u]];
}
if(u == v) return;
update(,pos[v] + ,pos[u],sum);
}
int main(){
scanf("%d%d%d%d",&N,&M,&S,&T); init();
for(int i = ; i <= M ; i ++){
int u,v; Sca2(u,v); LL w; Scl(w);
add(u,v,w); add(v,u,w);
e[i] = E(u,v,w); e[i].flag = ;
}
Dijkstra(T); init();
for(int i = ; i <= M ; i ++){
if(fa[e[i].u] == e[i].v || fa[e[i].v] == e[i].u){
add(e[i].v,e[i].u,e[i].w);
add(e[i].u,e[i].v,e[i].w);
}else e[i].flag = ;
}
dfs1(T,T); dfs2(T,T);
Build(,,N);
for(int i = ; i <= M ; i ++){
if(e[i].flag) continue;
LL sum = dis[e[i].u] + dis[e[i].v] + e[i].w;
int l = lca(e[i].u,e[i].v);
update(e[i].u,l,sum); update(e[i].v,l,sum);
}
for(int i = ; i <= N; i ++) dis2[i] = query(,pos[i]) - dis[i];
for(int i = ; i <= N ; i ++) dis[i] = 1e18; init();
for(int i = ; i <= M ; i ++){
add(e[i].u,e[i].v,e[i].w);
add(e[i].v,e[i].u,e[i].w);
}
priority_queue<node>Q;
Q.push(node(T,)); dis[T] = ;
while(!Q.empty()){
node u = Q.top(); Q.pop();
if(dis[u.pos] < u.cost) continue;
for(int i = head[u.pos]; ~i ; i = edge[i].next){
int v = edge[i].to;
if(dis[v] > max(dis[u.pos] + edge[i].dis,dis2[v])){
dis[v] = max(dis[u.pos] + edge[i].dis,dis2[v]);
Q.push(node(v,dis[v]));
}
}
}
if(dis[S] >= 1e16) puts("-1");
else Prl(dis[S]);
return ;
}

L

M.用SG函数打表博弈,反正我是不会做,贴上队友代码

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <map>
#include <set>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <queue> using namespace std; typedef long long LL;
const int maxn = 1e6+;
int if_pre[maxn +]; void pre_first()
{
memset(if_pre, 0x3f, sizeof(if_pre));
if_pre[] = ;
if_pre[] = ;
int pre_num =;
for (int i = ; i < maxn; i++)
{
if (if_pre[i] == 0x3f3f3f3f)
{
if_pre[i] = pre_num++;
for (int j = i << ; j < maxn; j += i)
{
if_pre[j] = min(if_pre[j],if_pre[i]);
}
}
}
} int main()
{
int t;
cin >>t;
pre_first();
while (t --)
{
int n,a;
cin >>n;
int sum =;
while (n--)
{
cin >>a;
sum^=if_pre[a];
//cout<<a<<'*'<<if_pre[a]<<endl;
}
if (sum)
cout<<"Subconscious is our king!"<<endl;
else
cout<<"Long live with King Johann!"<<endl; } #ifdef VSCode
system("pause");
#endif
return ;
}

M

HZNU第十二届校赛赛后补题的更多相关文章

  1. 台州学院第十二届校赛记录(B,C,E,H,I,J,L)

    传送门:点我 题目很棒,感谢出题验题的大佬们. 细节坑不少,是好事. 还是很菜,继续加油! B: 桃子的生日 时间限制(普通/Java):1000MS/3000MS     内存限制:65536KBy ...

  2. Little Sub and Traveling(杭师大第十二届校赛E题) 欧拉回路

    题目传送门 题目大意: 从0出发,每次只能跳到(i*2)%n或者(i*2+1)%n,求字典序最大的哈密顿回路. 思路: 首先n为奇数时无解,先来证明这一点. 先假设n为奇数,若要回到原点,则必定有一步 ...

  3. Little Sub and Piggybank (杭师大第十二届校赛G题) DP

    题目传送门 题意:每天能往存钱罐加任意实数的钱,每天不能多于起那一天放的钱数.如果某一天的钱数恰好等于那天的特价商品,则可以买,求最后的最大快乐值. 思路:先来一段来自出题人的题解: 显然的贪心:如果 ...

  4. 2018 HDU多校第四场赛后补题

    2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...

  5. 2018 HDU多校第三场赛后补题

    2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...

  6. 2018 CCPC 桂林站(upc复现赛)补题

    2018 CCPC 桂林站(upc复现赛)补题 G.Greatest Common Divisor(思维) 求相邻数的差值的gcd,对gcd分解素因子,对所有的素因子做一次遍历,找出最小答案. 几个样 ...

  7. 湖南省第十二届省赛:Parenthesis

    Description Bobo has a balanced parenthesis sequence P=p1 p2…pn of length n and q questions. The i-t ...

  8. ZOJ 3955 Saddle Point 校赛 一道计数题

    ZOJ3955 题意是这样的 给定一个n*m的整数矩阵 n和m均小于1000 对这个矩阵删去任意行和列后剩余一个矩阵为M{x1,x2,,,,xm;y1,y2,,,,,yn}表示删除任意的M行N列 对于 ...

  9. 福州大学第十届校赛 & fzu 2128最长子串

    思路: 对于每个子串,求出 母串中 所有该子串 的 开始和结束位置,保存在 mark数组中,求完所有子串后,对mark数组按 结束位置排序,然后 用后一个的结束位置 减去 前一个的 开始 位置 再 减 ...

随机推荐

  1. django 创建admin用户名跟密码

    一.django中创建用户名和密码 (venv) D:\project\py37project\Djangopro\Procrm>Python37 manage.py createsuperus ...

  2. LeetCode算法题-Employee Importance(Java实现)

    这是悦乐书的第291次更新,第309篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第159题(顺位题号是690).定义员工信息的数据结构,其中包括员工的唯一ID,他的重要 ...

  3. LeetCode算法题-Next Greater Element I(Java实现)

    这是悦乐书的第244次更新,第257篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第111题(顺位题号是496).你有两个数组(没有重复)nums1和nums2,其中nu ...

  4. C#基础知识之泛型

    泛型在c#中有很重要的位置,对于写出高可读性,高性能的代码有着关键的作用. 其实官方文档说明的很详细,我这边算是做个记录吧 一.什么是泛型? 泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) ...

  5. PHP7--PHP的一次重大变革

    PHP7--PHP的一次重大变革 一.写在开头 PHP7是PHP编程语言全新的一个版本,主要在性能方面获得了极大的提升.官方的文档显示,PHP7可以达到PHP5.x版本两倍的性能.同时还对PHP的语法 ...

  6. 通过supper()有参构造器,完成子类对象调用父类属性的方法,并完成赋值

    package com.Summer_0426.cn; /** * @author Summer * 通过supper()有参构造器,完成子类对象调用父类属性的方法,并完成赋值 * */ public ...

  7. 2019年美国大学生数学建模竞赛(MCM/ICM) E题解题思路

    这也许是我大学生涯最后一次参加数学建模比赛了吧,这次我们选择的问题是E题,以下是我们解题时候的一些思路.很多不易体现的项目产生对环境造成影响的指标可以由一些等同类型的指标来代替,如土地.森林植被被破环 ...

  8. c语言之数据类型

    #include<stdio.h> int main(void) { float weight, value; printf("Are you worth your weight ...

  9. HTTP协议中的短轮询、长轮询、长连接和短连接,看到一篇文章有感

    关于短轮询.长轮询 短轮询主要是前端实现,JS写个死循环,不停的去请求服务器中的库存量是多少,然后刷新到这个页面当中,这其实就是所谓的短轮询. 长轮询主要取决于服务器,在长轮询中,服务器如果检测到数据 ...

  10. 图论专题1考试Problem1

    Problem 1. bricksInput file: bricks.inOutput file: bricks.outTime limit: 1 secondjyb 在BUAA 天天被大神虐,所以 ...