A.张经理的员工
链接:https://ac.nowcoder.com/acm/contest/5403/A
来源:牛客网
张经理的公司的办公室长达100000米,从最左端开始每间隔1米都有一个工位(从第1米开始有工位),位于第i米的工位称为i号工位,且这些工位都在一条水平线上。他有n个员工,每个员工分别位于xi号工位上(不同员工可能位于同一个工位)。
现在张经理想把员工聚集在某两个工位上,他有q套方案(每套方案包含两个工位号,两个工位号可能相同),他想知道对于每套方案,所有员工都到达两个工位中的某一个所需走的最短路径之和是多少。
现在张经理想把员工聚集在某两个工位上,他有q套方案(每套方案包含两个工位号,两个工位号可能相同),他想知道对于每套方案,所有员工都到达两个工位中的某一个所需走的最短路径之和是多少。
输入描述:
第一行输入两个正整数n, q
第二行输入n个正整数xi,分别代表第i个员工的工位
之后q行每行输入两个整数a,b,代表该套方案要求的两个集合位置
(1<=n,q,xi,a,b<=105)(1<=n,q,xi,a,b<=10^5)(1<=n,q,xi,a,b<=105)
第二行输入n个正整数xi,分别代表第i个员工的工位
之后q行每行输入两个整数a,b,代表该套方案要求的两个集合位置
(1<=n,q,xi,a,b<=105)(1<=n,q,xi,a,b<=10^5)(1<=n,q,xi,a,b<=105)
输出描述:
对于每套方案,输出一个整数代表答案,每个答案独占一行。
示例1
输入
复制输出
复制#include <bits/stdc++.h> using namespace std; #define ll long long const int maxn = 100005; int a[maxn] , b[maxn]; ll pre[maxn] , fpre[maxn]; ll cpre[maxn] , cfpre[maxn]; int main() { int n,q; cin>>n>>q; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[a[i]]++; } ll sum = 0,sum2 = 0; for(int i=1;i<=100000;i++){ if(b[i]){ sum += 1ll*i*b[i]; sum2 += 1ll*b[i]; } pre[i] = sum; cpre[i] = sum2; } sum = 0,sum2 = 0; for(int i=100000;i>=1;i--){ if(b[i]){ sum += 1ll*i*b[i]; sum2 += 1ll*b[i]; } fpre[i] = sum; cfpre[i] = sum2; } while(q--){ int l,r; ll ans = 0; scanf("%d %d",&l,&r); if(l > r) swap(l , r); ll x = 1ll*cpre[l]*l - 1ll*pre[l]; ll y = 1ll*fpre[r] - 1ll*cfpre[r]*r; ll z = 0 , w = 0; if(r - l > 1){ int x = r - l; int l2 = l + x/2; z = pre[l2] - pre[l] - (cpre[l2] - cpre[l])*l; int r2 = l2; w = r*(cpre[r-1] - cpre[r2]) - (pre[r-1] - pre[r2]); } cout<<x + y + z + w<<endl; } return 0; }
B.随机序列
链接:https://ac.nowcoder.com/acm/contest/5403/B
来源:牛客网
国中生Chino总是做不完数学作业,Cocoa想来帮忙,但作业太多了,怎么也做不完。
Chino的数学作业由 T(1≤T≤100)T(1\leq T\leq 100)T(1≤T≤100)张试卷组成,每张试卷上有n(1≤n≤103)n(1\leq n\leq 10^3)n(1≤n≤103)个数a1..n(1≤a≤5000)a_{1..n}(1\leq a\leq 5000)a1..n(1≤a≤5000),Chino需要算出这些数的极差和方差。极差是一个整数,方差是一个浮点数,要求保留到小数点后3位。
虽然题目很简单,但计算量对于Chino来说实在太大啦!你能帮一帮她吗?
P.S.:一个数列的极差是指数列中最大的数减去最小的数,方差是指算出数列中每个数与数列平均值之差的平方后,对其求和,再除以数列元素个数得到的结果。
Chino的数学作业由 T(1≤T≤100)T(1\leq T\leq 100)T(1≤T≤100)张试卷组成,每张试卷上有n(1≤n≤103)n(1\leq n\leq 10^3)n(1≤n≤103)个数a1..n(1≤a≤5000)a_{1..n}(1\leq a\leq 5000)a1..n(1≤a≤5000),Chino需要算出这些数的极差和方差。极差是一个整数,方差是一个浮点数,要求保留到小数点后3位。
虽然题目很简单,但计算量对于Chino来说实在太大啦!你能帮一帮她吗?
P.S.:一个数列的极差是指数列中最大的数减去最小的数,方差是指算出数列中每个数与数列平均值之差的平方后,对其求和,再除以数列元素个数得到的结果。
输入描述:
输入的第一行有一个数T,表示试卷的数量;接下来的每2行,第一行有一个数n,表示当前试卷上数字的个数;第二行有n个数字
aia_iai,表示这张试卷上的每一个数。
输出描述:
对每张试卷,输出一行两个数,分别表示这些数字的极差和方差,中间用空格分开。其中极差是整数,方差是保留到小数点后3位的浮点数。
示例1
输入
2 5 5 4 3 2 1 7 333 494 655 991 101 591 941
输出
4 2.000 890 86075.959
#include<stdio.h> #include<math.h> int main() { int t,n,s[10000]; int i,j; int jc; // float aver,num=0,sum=0; double m; scanf("%d",&t); while(t--) { double aver,num=0,sum=0; scanf("%d",&n); for(i=0;i<n;i++) { scanf("%d",&s[i]); sum+=s[i]; } int min=10000,max=-1; for(i=0;i<n;i++) { if(s[i]<=min)min=s[i]; if(s[i]>=max)max=s[i]; } jc=max-min; aver=sum/n; for(i=0;i<n;i++) { m=(s[i]-aver)*(s[i]-aver); num+=m; } //printf("%.4lf\n",num); num/=n; printf("%d %.3lf\n",jc,num); } }
C.王国
链接:https://ac.nowcoder.com/acm/contest/5403/C
来源:牛客网
这个世界上有
n(n≤105)n(n\le 10^5)n(n≤105)个王国,有n-1条道路,任意两个王国相互可达. 每个王国都有属于某个势力,王国i属于势力ai(ai≤n)a_i(a_i\le n)ai(ai≤n) ,势力相同的王国想要相互联络.王国a与王国b的联络难度为x2x^2x2(x为a到b简单路径上边的数量)
输出最大的联络难度.
输出最大的联络难度.
输入描述:
第一行为正数n,表示王国数量
第二行为n个正整数,a1,a2...ana_1,a_2...a_na1,a2...an ,aia_iai 表示王国i所属的势力.
接下来的n-1行,每行2个正整数u,v. 表示王国u与王国v有道路相连.
输出描述:
输出最大联络难度
示例1
输入
7 1 1 2 3 3 3 1 1 2 1 3 2 4 2 5 3 6 1 7
输出
16
说明
王国4与王国6联系的难度为16
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll inf=0x3f3f3f3; const int N=2e5+10; int dfn[N],numdfn; int n,max_deep; int a[N]; /* lca部分 */ struct LCA { int head[N],dep[N],fa[N][22],cnt; struct edge { int v,w,next; }e[N*2]; void add(int u,int v,int w) { e[++cnt]={v,w,head[u]};head[u]=cnt; e[++cnt]={u,w,head[v]};head[v]=cnt; } void dfs(int u,int d,int f) { dep[u]=d;fa[u][0]=f; dfn[u]=++numdfn; max_deep=max(max_deep,d); for(int i=head[u];i;i=e[i].next) { int v=e[i].v; if(v==f) continue; dfs(v,d+1,u); } } void init() { dfs(1,0,1); for(int k=1;k<=20;++k) for(int i=1;i<=n;++i) fa[i][k]=fa[fa[i][k-1]][k-1]; } int lca(int u,int v) { if(dep[u]<dep[v]) swap(u,v); for(int k=20;k>=0;--k) if(dep[fa[u][k]]>=dep[v]) u=fa[u][k]; if(u==v) return v; for(int k=20;k>=0;--k) if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k]; return fa[u][0]; } int findlen(int u,int v) { return dep[u]+dep[v]-2*dep[lca(u,v)]; } }L; /* 虚树部分 */ vector<int>has[N]; vector<pair<int,int> >G[N]; int st[N],top,cnt; int numid; bool cmp(int x,int y) { return dfn[x]<dfn[y]; } void ins(int id,int x)//插入虚树新点 { if(top==1){st[++top]=x;return ;} int fa=L.lca(x,st[top]); if(fa==st[top]){//就在该链的下方 st[++top]=x;return ; } while(top>1&&dfn[st[top-1]]>=dfn[fa]){ int p1=st[top],p2=st[top-1];//该相邻两节点相连 //建虚树图 int w=L.findlen(p1,p2); G[p1].emplace_back(make_pair(p2,w)); G[p2].emplace_back(make_pair(p1,w)); --top; } if(st[top]!=fa){ int p1=st[top],p2=fa; int w=L.findlen(p1,p2); G[p1].emplace_back(make_pair(p2,w)); G[p2].emplace_back(make_pair(p1,w)); st[top]=fa; } st[++top]=x; } void build(int id,vector<int>& has) { sort(has.begin(),has.end()); has.erase(unique(has.begin(),has.end()),has.end()); sort(has.begin(),has.end(),cmp); st[top=1]=1; //top=0; for(int v:has) ins(id,v); //printf("top:%d\n",top); while(top>1) { int p1=st[top],p2=st[top-1]; int w=L.findlen(p1,p2); G[p1].emplace_back(make_pair(p2,w)); G[p2].emplace_back(make_pair(p1,w)); --top; } } int mx,mi; int tar; void dfs1(int u,int fa,int dep,int val,int ty) { //printf("u:%d fa:%d\n",u,fa); if(a[u]==ty&&dep>mi){ mi=dep,tar=u; } for(auto now:G[u]){ if(now.first==fa) continue; if(now.first==u) continue;//1可能跟自己又连了一条边 //printf("fa:%d u:%d v:%d w:%d\n",fa,u,now.first,now.second); dfs1(now.first,u,dep+now.second,val,ty); } if(val==1) G[u].clear(); } int bfs(int rt,int ty) { mi=-1; dfs1(rt,-1,0,0,ty); mi=-1; // puts(""); // printf("tar:%d\n",tar); // puts(""); dfs1(tar,-1,0,1,ty); // printf("ty:%d mi:%d\n",ty,mi); // puts(""); // puts(""); return mi; } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); has[a[i]].push_back(i); mx=max(mx,a[i]); } for(int i=1;i<n;++i){ int u,v; scanf("%d%d",&u,&v); L.add(u,v,1); } L.init(); int ans=0; for(int i=1;i<=mx;++i){ if(has[i].size()==0) continue; build(i,has[i]); ans=max(ans,bfs(has[i][0],i)); } printf("%lld\n",1ll*ans*ans); }
D卡拉兹函数
链接:https://ac.nowcoder.com/acm/contest/5403/D
来源:牛客网
卡拉兹函数是怎么回事呢?卡拉兹相信大家都很熟悉,但是卡拉兹函数是怎么回事呢,下面就让小编带大家一起了解吧。
卡拉兹函数,其实就是当n是奇数时,输出3*n+1,当n是偶数时,输出n/2,大家可能会很惊讶卡拉兹怎么会是函数呢?但事实就是这样,小编也感到非常惊讶。
卡拉兹函数,其实就是当n是奇数时,输出3*n+1,当n是偶数时,输出n/2,大家可能会很惊讶卡拉兹怎么会是函数呢?但事实就是这样,小编也感到非常惊讶。
这就是关于卡拉兹函数的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!
输入描述:
一个不超过10
5
的正整数n
输出描述:
一行一个整数k。当n是奇数时,k=3*n+1,当n是偶数时,k=n/2。
示例1
输入
1
输出
4
说明
示例2
输入
2
输出
1
#include<stdio.h> #include<math.h> int main() { int n; long long k; while(scanf("%d",&n)!=EOF) { if(n%2!=0) { k=3*n+1; printf("%lld\n",k); } else { k=n/2; printf("%lld\n",k); } } }
E张经理的字符串
链接:https://ac.nowcoder.com/acm/contest/5403/E
来源:牛客网
张经理有n个字符串和一个转化表,转化表里记录了m个字符串。
张经理对其拥有的字符串可以进行3种操作:
1、在一个字符串末尾删除一个字符
2、在一个字符串末尾添加一个任意字符
3、若有一字符串s等于转化表中记录的某一字符串,则可将s转化为转化表中记录的任一字符串
张经理的舍友要送给他一个字符串p,但只告诉张经理p等于他拥有的某一字符串的某一非空前缀。
张经理想知道当p分别等于其拥有的每个串的每个非空前缀时,将其拥有的串和p转化为相同字符串(可以为空)需要的最少操作数。
张经理对其拥有的字符串可以进行3种操作:
1、在一个字符串末尾删除一个字符
2、在一个字符串末尾添加一个任意字符
3、若有一字符串s等于转化表中记录的某一字符串,则可将s转化为转化表中记录的任一字符串
张经理的舍友要送给他一个字符串p,但只告诉张经理p等于他拥有的某一字符串的某一非空前缀。
张经理想知道当p分别等于其拥有的每个串的每个非空前缀时,将其拥有的串和p转化为相同字符串(可以为空)需要的最少操作数。
输入描述:
第一行输入两个整数n,m(1<=n, m<=40)
第2到n+1行输入张经理拥有的n个字符串
第n+2行到n+m+1行输入转化表中的m个字符串
每个字符串都由小写英文字母组成,且长度不超过400
输出描述:
分别输出当p等于张经理拥有的每个串的每个非空前缀时(字符串按输入顺序,前缀按从短到长),张经理将其所有的串和p转化为相同字符串(可以为空)所需的最少操作数,数字间用空格间隔。
示例1
输入
2 2 abcd ab abcd ab
输出
2 1 2 1 2 1
说明
示例2
输入
4 2 a b b b npu acm
输出
4 2 2 2
#pragma GCC optimize(2) #include<bits/stdc++.h> #define maxn 100100 using namespace std; int n, m, vis[maxn], dis[maxn], sum[maxn]; int lenA[45], lenB[45], tree[maxn][27], tot=1, posA[45][405], posB[45][405]; vector<int> edge[maxn]; string A[45], B[45]; void insert(string s, int pos[][405], int p) { int len=s.size(), rt=1, id; for (int i=0; i<len; i++) { id=s[i]-'a'; if (!tree[rt][id]) { tree[rt][id]=++tot; edge[rt].push_back(tot); edge[tot].push_back(rt); } rt=tree[rt][id]; pos[p][i]=rt; } } void dijkstra(int s, int f) { priority_queue<pair<int, int> > pq; if (f==0) { memset(dis, 127, sizeof(dis)); dis[s]=0; pq.push(make_pair(0, s)); } else { for (int i=1; i<=tot; i++) { dis[i]=sum[i]; pq.push(make_pair(-dis[i], i)); } } while (!pq.empty()) { auto temp=pq.top(); pq.pop(); temp.first*=-1; if (dis[temp.second]!=temp.first) continue; for (auto i: edge[temp.second]) { if (dis[i] > dis[temp.second]+1) { dis[i]=dis[temp.second]+1; pq.push(make_pair(-dis[i], i)); } } } } int main() { cin>>n>>m; for (int i=1; i<=n; i++) { cin>>A[i]; lenA[i]=A[i].size(); } for (int i=1; i<=m; i++) { cin>>B[i]; lenB[i]=B[i].size(); } for (int i=1; i<=n; i++) insert(A[i], posA, i); for (int i=1; i<=m; i++) insert(B[i], posB, i); for (int i=1; i<=m; i++) for (int j=i+1; j<=m; j++) { edge[posB[i][lenB[i]-1]].push_back(posB[j][lenB[j]-1]); edge[posB[j][lenB[j]-1]].push_back(posB[i][lenB[i]-1]); } for (int i=1; i<=n; i++) { dijkstra(posA[i][lenA[i]-1], 0); for (int j=1; j<=tot; j++) sum[j]+=dis[j]; } dijkstra(0, 1); for (int i=1; i<=n; i++) { for (int j=0; j<lenA[i]; j++) cout<<dis[posA[i][j]]<<" "; } return 0; }
F四等分的角度
链接:https://ac.nowcoder.com/acm/contest/5403/F
来源:牛客网
输入点A、O、B的坐标,找任意三个点
K1K_1K1、K2K_2K2、K3K_3K3,使得射线OK1OK_1OK1、OK2OK_2OK2、OK3OK_3OK3把∠AOB四等分(∠AOB<180°)。
输入描述:
三行,每行两个整数
xix_ixi,yiy_iyi,依次表示A、O、B的坐标。数据保证A、O、B三点不共线,且O点坐标绝对值均不超过10910^9109、向量OA\boldsymbol{OA}OA、OB\boldsymbol{OB}OB的模均在[1,105)[1,10^5)[1,105)范围内。
输出描述:
三行,每行两个浮点数
xKix_{K_i}xKi,yKiy_{K_i}yKi,表示点KiK_iKi的坐标。
注意KiK_iKi输出的顺序:设PiP_iPi为线段AB与射线OKiOK_iOKi的交点,要求点A、P1P_1P1、P2P_2P2、P3P_3P3、B在线段AB上依次排列。(不要求KiK_iKi必须在三角形外部)
精度要求:如果对每个输出的答案KiK_iKi,向量OKi\boldsymbol{OK_i}OK
注意KiK_iKi输出的顺序:设PiP_iPi为线段AB与射线OKiOK_iOKi的交点,要求点A、P1P_1P1、P2P_2P2、P3P_3P3、B在线段AB上依次排列。(不要求KiK_iKi必须在三角形外部)
精度要求:如果对每个输出的答案KiK_iKi,向量OKi\boldsymbol{OK_i}OK