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