愉快的校赛翻皮水!

题解

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. 【公众号系列】SAP HANA和区块链

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[公众号系列]SAP HANA和区块链   写在 ...

  2. 启动期间的内存管理之初始化过程概述----Linux内存管理(九)

    在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到保护模式, 然后内核才能检 ...

  3. C# 中使用特性获得函数被调用的路径,行号和函数

    自从 .net framework 4.5  增加了几个特性来获得函数的调用路径(CallerFilePath),调用行号(CallerLineNumber),和调用函数(CallerMemberNa ...

  4. git 命令添加整个文件夹以及文件夹下的内容

    对于一个文件夹提交到服务器上,喜欢用 git add .(后面为".") 这种情况对于一个文件夹的还是很有用的,但出现了多个不同文件夹后,要分别提交就不能这么用了, 可以使用如下指 ...

  5. SystemTap Beginners Guide

    SystemTap 3.0 SystemTap Beginners Guide Introduction to SystemTap Edition 3.0   Red Hat, Inc. Don Do ...

  6. 详解vuex结合localstorage动态监听storage的变化

    这篇文章主要介绍了详解vuex结合localstorage动态监听storage的变化,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 需求:不同组件间共用同一数据,当一个 ...

  7. apt-get 详解&&配置阿里源

    配置apt-get的下载源 1.复制原文件备份 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 2.编辑源列表文件 sudo vim / ...

  8. 利用SQL注入漏洞登录后台

    所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询 ...

  9. 主成分分析 —PCA

    一.定义 主成分分析(principal components analysis)是一种无监督的降维算法,一般在应用其他算法前使用,广泛应用于数据预处理中.其在保证损失少量信息的前提下,把多个指标转化 ...

  10. C# — 调用dll出现试图加载不正确格式的程序问题

    今天在调用百度dll包时,运行项目出现了如下警告: 修改:鼠标右击项目名称----选择属性----生成-----平台目标-----X64(由于我调用的是X64的dll包,所以这里选择X64,网上许多说 ...