2015 Multi-University Training Contest 6
1001 Average
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2086 Accepted Submission(s): 158
Special Judge
Each soda has some candies in their hand. And they want to make the number of candies the same by doing some taking and giving operations. More specifically, every two adjacent soda x and y can do one of the following operations only once:
1. x-th soda gives y-th soda a candy if he has one;
2. y-th soda gives x-th soda a candy if he has one;
3. they just do nothing.
Now you are to determine whether it is possible and give a sequence of operations.
The first contains an integer n (1≤n≤105), the number of soda.
The next line contains n integers a1,a2,…,an (0≤ai≤109), where ai denotes the candy i-th soda has.
题意: 执行上述三种操作的其中一种操作, x给y 1个值,或者y给x 1个值,x与y必须相邻。
解法: 不能整除不符合题意, 需要注意的细节比较多,总体上是这样, a[i]与均值作比较, 如果小1那么就从i+1那里拿,大1就给i+1, 等于的话不做任何处理。
但是对于第一个值要进行特殊处理。。 这个当时没有想清楚怎么处理, 看了题解后才晓得, , 现在就特想知道, 为什么这么想。
#include<bits/stdc++.h> #define N 100010 #define LL long long using namespace std; int f[N],p[N]; int x[N],y[N]; int m,n; LL sum; bool work() { for (int i=1;i<=n;i++) if (f[i]!=sum/n) return false; return true; } bool all_same() { for (int i=1; i<=n; ++ i) if (p[i]!=sum/n) return false; return true; } bool solve() { for (int i = 2; i<n; ++i) { if (f[i] == sum/n) continue; else if (f[i] <sum/n) x[m] = i + 1, y[m++] = i,f[i]++,f[i+1]--; else if (f[i] >sum/n) x[m] = i, y[m++] = i + 1,f[i]--,f[i+1]++; } if (f[n] <sum/n) x[m] = 1, y[m++] = n,f[n]++,f[1]--; else if (f[n] >sum/n) x[m] = n, y[m++] = 1,f[n]--,f[1]++; return work(); } void print() { printf("YES\n%d\n",m); for (int i=0;i<m;i++) printf("%d %d\n",x[i],y[i]); } int main() { int T; scanf("%d",&T); while(T--) { sum=0; scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&p[i]); sum+=p[i]; } if (sum%n!=0) { printf("NO\n"); continue; } if (all_same()) { printf("YES\n0\n"); continue; } if (p[1]>=sum/n) { for (int i=1;i<=n;i++) f[i]=p[i]; m=0; x[m]=1; y[m++]=2; f[1]--; f[2]++; if (solve()) {print(); continue;} } if (p[1]<=sum/n) { for (int i=1;i<=n;i++) f[i]=p[i]; m=0; x[m]=2; y[m++]=1; f[1]++; f[2]--; if (solve()) {print(); continue;} } for (int i=1;i<=n;i++) f[i]=p[i]; m=0; if (solve()) {print(); continue;} printf("NO\n"); } return 0; }
1003 Cake
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1093 Accepted Submission(s): 521
Special Judge
Note that you cannot divide a whole cake into small pieces that is each cake must be complete in the m parts. Each cake must belong to exact one of m parts.
The first contains two integers n and m (1≤n≤105,2≤m≤10), the number of cakes and the number of soda.
It is guaranteed that the total number of soda in the input doesn’t exceed 1000000. The number of test cases in the input doesn’t exceed 1000.
If it is possible, then output m lines denoting the m parts. The first number si of i-th line is the number of cakes in i-th part. Then si numbers follow denoting the size of cakes in i-th part. If there are multiple solutions, print any of them.
#include<bits/stdc++.h> #define N 50 #define LL long long using namespace std; vector<int> G[10]; bool visit[N]; int a[N][N]; bool dfs(int k, int sum, int n,int m) { bool flag=false; if (k==m) return true; for (int i=n;i>=1;i--) if (!visit[i]&&sum>=i) { visit[i]=true; a[k][++a[k][0]]=i; if (sum==i) flag=dfs(k+1,(n+1)*n/2/m,n,m); else flag=dfs(k,sum-i,n,m); if (flag) return true; a[k][0]--; visit[i]=false; } return false; } int main() { int T,m; LL n; scanf("%d",&T); while(T--) { scanf("%I64d%d",&n,&m); for (int i=0;i<m;i++) G[i].clear(); if ((n+1)*n/2%m!=0||n<2*m-1) { printf("NO\n"); continue; } while(n>40) { for (int i=0;i<m;i++) G[i].push_back(n-i); for (int i=0;i<m;i++) G[i].push_back(n-2*m+i+1); n=n-2*m; } for (int i=0;i<m;i++) a[i][0]=0; memset(visit,0,sizeof(visit)); dfs(0,(n+1)*n/2/m,n,m); for (int i=0;i<m;i++) for (int j=1;j<=a[i][0];j++) G[i].push_back(a[i][j]); printf("YES\n"); for (int i=0;i<m;i++) { printf("%d",(int)G[i].size()); for (int j=0;j<(int)G[i].size();j++) printf(" %d",G[i][j]); printf("\n"); } } return 0; }
1006 First One
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1971 Accepted Submission(s): 103
Note: In this problem, you can consider log20 as 0.
The first line contains an integer n (1≤n≤105), the number of integers in the array.
The next line contains n integers a1,a2,…,an (0≤ai≤105).
//二分位置会超时 //时间复杂度nlgn #include<bits/stdc++.h> #define N 100010 #define LL long long using namespace std; int pos[N][40]; int f[N]; int main() { int T,n; LL ans; scanf("%d",&T); while(T--) { ans=0; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&f[i]); for (int k=0;k<36;k++) { LL pi=1LL<<(k+1),sum=f[1]; int j=1; for (int i=1;i<=n;i++) { sum=sum-f[i-1]; while(j<=n&&sum<pi) sum=sum+f[++j]; pos[i][k]=j-1; } } for (int i=1;i<=n;i++) { LL l=i,r; for (int k=0;k<36;k++) { r=pos[i][k]; ans=ans+(k+1)*((r-l+1)*(i+l)+(r-l+1)*(r-l)/2); l=r+1; } } printf("%I64d\n",ans); } return 0; }
1008 Hiking
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 911 Accepted Submission(s): 352
Special Judge
1. he selects a soda not invited before;
2. he tells soda the number of soda who agree to go hiking by now;
3. soda will agree or disagree according to the number he hears.
Note: beta will always tell the truth and soda will agree if and only if the number he hears is no less than li and no larger than ri, otherwise he will disagree. Once soda agrees to go hiking he will not regret even if the final total number fails to meet some soda's will.
Help beta design an invitation order that the number of soda who agree to go hiking is maximum.
The first contains an integer n (1≤n≤105), the number of soda. The second line constains n integers l1,l2,…,ln. The third line constains n integers r1,r2,…,rn. (0≤li≤ri≤n)
It is guaranteed that the total number of soda in the input doesn't exceed 1000000. The number of test cases in the input doesn't exceed 600.
思路: 在左端点可以到达的情况下,r越小越好, 利用这种贪心思想来做, 代码很惊艳。
#include<bits/stdc++.h> #define N 100010 using namespace std; struct node { int l,r,z; bool operator<(const node &b) const { if (r<b.r) return true; if (r==b.r&&l<b.l) return true; if (r==b.r&&l==b.l&&z<b.z) return true; return false; } }; set<node> S; node f[N],p[N]; bool visit[N]; int ans[N]; bool cmp1(node a, node b) { if (a.l<b.l) return true; if (a.l==b.l&&a.r<b.r) return true; return false; } bool cmp2(node a, node b) { if (a.r<b.r) return true; if (a.r==b.r&&a.l<b.l) return true; return false; } int main() { int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(visit,0,sizeof(visit)); for (int i=0;i<n;i++) scanf("%d",&f[i].l); for (int i=0;i<n;i++) scanf("%d",&f[i].r); for (int i=0;i<n;i++) { f[i].z=i+1; p[i]=f[i]; } sort(f,f+n,cmp1); sort(p,p+n,cmp2); int now=0,pl=0,pr=0; while(1) { while(pl<n&&f[pl].l<=now) S.insert(f[pl++]); while(pr<n&&p[pr].r<now) S.erase(p[pr++]); if (S.empty()) break; visit[(*(S.begin())).z]=true; ans[now++]=(*(S.begin())).z; S.erase(S.begin()); } printf("%d\n",now); for (int i=0;i<now;i++) printf("%d ",ans[i]); for (int i=1;i<=n;i++) if (!visit[i]) printf("%d ",i); printf("\n"); } return 0; } /* 4 8 4 1 3 2 2 1 0 3 5 3 6 4 2 1 7 6 8 3 3 2 0 5 0 3 6 4 5 2 7 7 6 7 6 8 2 2 3 3 3 0 0 2 7 4 3 6 3 2 2 5 8 5 6 5 3 3 1 2 4 6 7 7 6 5 4 3 5 */
1009 In Touch
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 693 Accepted Submission(s): 76
The 1-st soda is their leader and he wants to know the minimum cost needed to reach i-th soda (1≤i≤n).
The first line contains an integer n (1≤n≤2×105), the number of soda.
The second line contains n integers l1,l2,…,ln. The third line contains n integers r1,r2,…,rn. The fourth line contains n integers c1,c2,…,cn. (0≤li≤ri≤n,1≤ci≤109)
#pragma comment(linker, "/STACK:102400000,102400000") #include<bits/stdc++.h> #define N 200000+10 #define inf 1e15 #define LL long long using namespace std; int l[N],r[N]; LL c[N],d[N]; struct node { int id; LL dis; node(int id, LL dis):id(id),dis(dis){} bool operator <(const node &b) const { if (dis+c[id]==b.dis+c[b.id]) return id<b.id; return dis+c[id]<b.dis+c[b.id]; } }; int main() { int T,n; scanf("%d",&T); while(T--) { set<node> p; set<int> q; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&l[i]); for (int i=1;i<=n;i++) scanf("%d",&r[i]); for (int i=1;i<=n;i++) scanf("%I64d",&c[i]); for (int i=1;i<=n;i++) d[i]=inf; d[1]=0; p.insert(node(1,0)); for (int i=2;i<=n;i++) q.insert(i); set<int>::iterator it; set<int>::iterator it2; while(!p.empty()) { int u=(*(p.begin())).id; LL val=(*(p.begin())).dis; p.erase(p.begin()); it=q.lower_bound(u-r[u]); while (it!=q.end()&&((*it>=u-r[u]&&*it<=u-l[u])||((*it>=u+l[u])&&(*it<=u+r[u])))) { d[*it]=val+c[u]; p.insert(node(*it,d[*it])); it2=it++; q.erase(it2); } it=q.lower_bound(u+l[u]); while (it!=q.end()&&((*it>=u-r[u]&&*it<=u-l[u])||((*it>=u+l[u])&&(*it<=u+r[u])))) { d[*it]=val+c[u]; p.insert(node(*it,d[*it])); it2=it++; q.erase(it2); } } printf("0"); for (int i=2;i<=n;i++) if (d[i]==inf) printf(" -1"); else printf(" %I64d",d[i]); printf("\n"); } return 0; }
1011 Key Set
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1476 Accepted Submission(s): 726
The first line contains an integer n (1≤n≤109), the number of integers in the set.