Codeforces Round #520 (Div. 2)
A.prank
题意:给出一个含有n个数的递增的序列,问最多能删除多少个连续的数字,使得这个数列还是只可能有这一种形式。
分析:那就找出一段最长的差为1的序列就行。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <stack> 8 #include <cmath> 9 #include <cstdlib> 10 #include <set> 11 #include <map> 12 13 14 using namespace std; 15 typedef long long LL; 16 typedef unsigned long long ull; 17 const int INF = 2147000000; 18 const LL inf = 1e18; 19 LL gcd(LL a,LL b){ 20 if(!b)return a; 21 return gcd(b,a%b); 22 } 23 const int maxn = 1e3+100; 24 int n; 25 int a[maxn]; 26 int main(){ 27 scanf("%d",&n); 28 for(int i = 1; i <= n; i++) 29 scanf("%d",&a[i]); 30 a[n+1]=1001; 31 int ans=0; 32 for(int i = 1;i <= n; i++){ 33 if(a[i]==a[i-1]+1){ 34 for(int j=i+1;j<=n+1;j++){ 35 if(a[j]==a[j-1]+1){ 36 ans=max(ans,j-i); 37 // printf("%d %d\n",i,j); 38 }else{ 39 break; 40 } 41 } 42 } 43 } 44 printf("%d\n",ans); 45 return 0; 46 }
B.Math
题意:给出一个正整数n,可以进行以下两种操作。1将n乘一个整数x。2将n开平方。问最少需要多少次操作能将n变得最小?
分析:将n唯一分解,n能变得最小得值就是n所有得质因子得乘积。次数就是先将所有质因子得次数都变成一个2得某次方,然后不断开方。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <stack> 8 #include <cmath> 9 #include <cstdlib> 10 #include <set> 11 #include <map> 12 13 14 using namespace std; 15 typedef long long LL; 16 typedef unsigned long long ull; 17 const int INF = 2147000000; 18 const LL inf = 1e18; 19 LL gcd(LL a,LL b){ 20 if(!b)return a; 21 return gcd(b,a%b); 22 } 23 int n; 24 const int maxn=1e6+100; 25 int prime[maxn],deg[maxn],A[maxn]; 26 int main(){ 27 A[0] = 1; 28 for(int i = 1; i <= 30; i++){ 29 A[i] = 2 * A[i-1]; 30 } 31 // printf("%d\n",A[30]); 32 scanf("%d",&n); 33 if(n == 1){ 34 printf("1 0\n"); 35 return 0; 36 } 37 int N = n, num = 0; 38 int m = (int)sqrt(n+0.5); 39 for(int i = 2; i <= m; i++){ 40 if(N%i == 0){ 41 num ++; 42 prime[num] = i; 43 while(N%i == 0){ 44 deg[num]++; 45 N /= i; 46 } 47 } 48 } 49 if(N > 1){ 50 num++; 51 prime[num] = N; 52 deg[num] ++; 53 } 54 // for(int i = 1; i <= num; i++){ 55 // printf("%d %d\n",prime[i],deg[i]); 56 // } 57 // printf("!!!\n"); 58 int ans = 1, ans1 = 1, Max = 0; 59 for(int i = 1; i <= num; i++){ 60 Max = max(Max , deg[i]); 61 } 62 int pos = lower_bound(A,A+31,Max) - A; 63 if(Max == A[pos]){ 64 ans1 = 0; 65 if(num!=1){ 66 for(int i = 1; i <= num; i++){ 67 if(Max != deg[i]){ 68 ans1 = 1; 69 break; 70 } 71 } 72 } 73 } 74 Max = A[pos]; 75 for(int i = 1; i <= num; i++){ 76 ans = ans * prime[i]; 77 } 78 ans1 += pos; 79 printf("%d %d\n",ans,ans1); 80 return 0; 81 }
C.Banh-mi
题意:略
分析:我对这个题完全没印象了···汗···
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <stack> 8 #include <cmath> 9 #include <cstdlib> 10 #include <set> 11 #include <map> 12 13 14 using namespace std; 15 typedef long long LL; 16 typedef unsigned long long ull; 17 const int mod = 1e9+7; 18 const int INF = 2147000000; 19 const LL inf = 1e18; 20 LL gcd(LL a,LL b){ 21 if(!b)return a; 22 return gcd(b,a%b); 23 } 24 const int maxn = 100000+100; 25 26 LL pow_mod(LL a,LL n,LL m){ 27 if(n==0)return 1; 28 LL x=pow_mod(a,n/2,m); 29 LL ans=(LL)x*x%m; 30 if(n%2==1)ans=ans*a%m; 31 return ans; 32 } 33 int n,q; 34 char s[maxn]; 35 int sum[maxn]; 36 int main(){ 37 scanf("%d%d",&n,&q); 38 scanf("%s",s); 39 for(int i = 0; i < n;i++){ 40 if(s[i]=='1'){ 41 sum[i] = sum[i-1] + 1; 42 }else{ 43 sum[i] = sum[i-1]; 44 } 45 } 46 for(int i = 1; i <= q; i++){ 47 int l , r; 48 scanf("%d%d",&l,&r); 49 l--;r--; 50 int num = sum[r]-sum[l-1]; 51 LL ans = 0; 52 int last = 1; 53 LL nn = r - l +1; 54 55 ans = (pow_mod(2,num,mod)-1); 56 ans =(ans+ ans*(pow_mod(2,nn-num,mod)-1)%mod)%mod; 57 printf("%I64d\n",ans); 58 } 59 return 0; 60 }
D.Fun with Integers
题意:给出一个大于等于2的正整数n,对于每一对正整数a,b,你可以将a变成b当存在一个x满足a*x = b或者b*x =a。每次变完以后的得分是|x|。问最大得分。
分析:我们发现,对于n以内的每一对满足条件的a,b都可以像样例那么变换。那么只要找出n以内成对的倍数就可以了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <stack> 8 #include <cmath> 9 #include <cstdlib> 10 #include <set> 11 #include <map> 12 13 14 using namespace std; 15 typedef long long LL; 16 typedef unsigned long long ull; 17 const int INF = 2147000000; 18 const LL inf = 1e18; 19 LL gcd(LL a,LL b){ 20 if(!b)return a; 21 return gcd(b,a%b); 22 } 23 int n; 24 LL ans; 25 int main(){ 26 scanf("%d",&n); 27 for(LL i = 2; i <= n/2; i++){ 28 for(LL j = 2; j*i <= n; j++){ 29 ans += 4*j; 30 } 31 } 32 printf("%I64d\n",ans); 33 return 0; 34 }
E.Company
题意:给出一课有n个点的树,和q个询问,每个询问给出一个区间[li,ri]。你可以删除区间内的一个结点,使得删除以后区间内点的lca深度最大。
分析:区间的lca怎么求?[l,r]内dfs序最大的点和最小的点的lca就是这个区间的lca。那要删除的点一定就是这两个点其中的一个。按照惯例我们用线段树维护就可以了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <stack> 8 #include <cmath> 9 #include <cstdlib> 10 #include <set> 11 #include <map> 12 13 14 using namespace std; 15 typedef long long LL; 16 typedef unsigned long long ull; 17 typedef pair<int,int>pir; 18 const int INF = 2147000000; 19 const LL inf = 1e18; 20 const int maxn = 100000 + 10; 21 int head[maxn],to[2*maxn],Next[2*maxn]; 22 int depth[maxn],order[maxn],idx[maxn];//order dfs序列,idx是dfs结点的dfs序 23 int f[maxn][30]; 24 int n,sz,q,maxd,N; 25 void init(){ 26 sz = 0; 27 N = 0; 28 memset(head,-1,sizeof(head)); 29 } 30 void add_edge(int a,int b){ 31 ++sz; 32 to[sz] = b; 33 Next[sz] = head[a]; 34 head[a] = sz; 35 } 36 void dfs(int u,int fa,int dep){ 37 depth[u] = dep; 38 f[u][0] = fa; 39 N++; 40 order[N] = u; 41 idx[u] = N; 42 for(int i = 1; i <= maxd; i++){ 43 f[u][i] = f[f[u][i-1]][i-1]; 44 } 45 for(int i = head[u]; i != -1; i = Next[i]){ 46 int v = to[i]; 47 if(v == fa) 48 continue; 49 dfs(v, u, dep + 1); 50 } 51 return; 52 } 53 pir minv[4*maxn],maxv[4*maxn]; 54 void build(int o,int L,int R){ 55 if(L == R){ 56 minv[o].first = idx[L]; 57 minv[o].second = L; 58 maxv[o] = minv[o]; 59 return ; 60 } 61 int M = L +(R - L)/2; 62 build(2*o,L,M); 63 build(2*o+1,M+1,R); 64 minv[o] = min(minv[2*o], minv[2*o+1]); 65 maxv[o] = max(maxv[2*o], maxv[2*o+1]); 66 } 67 68 pir query_min(int o,int L,int R,int ql,int qr){ 69 if(ql<=L&&qr>=R){ 70 return minv[o]; 71 } 72 int M = L + (R - L)/2; 73 pir res = make_pair(INF,INF); 74 if(ql <= M) 75 res = query_min(2*o,L,M,ql,qr); 76 if(qr > M) 77 res = min(res, query_min(2*o+1,M+1,R,ql,qr)); 78 return res; 79 } 80 81 pir query_max(int o,int L,int R,int ql,int qr){ 82 if(ql<=L&&qr>=R){ 83 return maxv[o]; 84 } 85 int M = L + (R - L)/2; 86 pir res = make_pair(-INF,-INF); 87 if(ql <= M) 88 res = query_max(2*o,L,M,ql,qr); 89 if(qr > M) 90 res = max(res, query_max(2*o+1,M+1,R,ql,qr)); 91 return res; 92 } 93 94 int lca(int u, int v){ 95 if(depth[u] > depth[v])swap(u,v); 96 for(int i = maxd; i >= 0; i--){ 97 if(depth[f[v][i]] >= depth[u]) 98 v = f[v][i]; 99 } 100 if(u == v) 101 return u; 102 for(int i = maxd; i >= 0; i--){ 103 if(f[u][i] != f[v][i]){ 104 u = f[u][i], v = f[v][i]; 105 } 106 } 107 return f[u][0]; 108 } 109 110 int main(){ 111 scanf("%d%d",&n,&q); 112 maxd = (int)(log(n)/log(2)) + 1; 113 //printf("%d\n",maxd); 114 init(); 115 for(int i = 2; i <= n; i++){ 116 int fa; 117 scanf("%d",&fa); 118 add_edge(fa,i); 119 add_edge(i,fa); 120 } 121 dfs(1,-1,1); 122 build(1,1,n); 123 124 for(int i = 1; i <= q; i++){ 125 int l , r; 126 scanf("%d%d",&l,&r); 127 pir Max = query_max(1,1,n,l,r); 128 pir Min = query_min(1,1,n,l,r); 129 int lc1,lc2; 130 //先尝试删最大的 131 pir max1 = make_pair(-INF,-INF); 132 if(Max.second > l) 133 max1 = query_max(1,1,n,l,Max.second-1); 134 if(Max.second < r) 135 max1 = max(max1,query_max(1,1,n,Max.second+1,r)); 136 lc1 = lca(max1.second,Min.second); 137 pir min1 = make_pair(INF,INF); 138 if(Min.second > l) 139 min1 = query_min(1,1,n,l,Min.second-1); 140 if(Min.second < r) 141 min1 = min(min1,query_min(1,1,n,Min.second+1,r)); 142 lc2 = lca(Max.second,min1.second); 143 if(depth[lc1] >= depth[lc2]){ 144 printf("%d %d\n",Max.second,depth[lc1]-1); 145 }else{ 146 printf("%d %d\n",Min.second,depth[lc2]-1); 147 } 148 } 149 return 0; 150 }
F.Upgrading Cities
这个题参考的一位巨巨的博客:https://blog.csdn.net/corsica6/article/details/84098779
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <queue> 6 7 8 using namespace std; 9 const int maxn = 300000+100; 10 int n,m,sz,l,r; 11 int head[maxn],Next[maxn],to[maxn],in[maxn],out[maxn],deg[maxn],q[maxn]; 12 void init(){ 13 sz = 0; 14 memset(deg,0,sizeof(deg)); 15 memset(head,-1,sizeof(head)); 16 } 17 void add_edge(int a,int b){ 18 ++sz; 19 to[sz] = b; 20 Next[sz] = head[a]; 21 head[a] = sz; 22 } 23 struct Edge{ 24 int from,to; 25 }edges[maxn]; 26 int main(){ 27 init(); 28 scanf("%d%d",&n,&m); 29 for(int i = 1; i <= m; i++){ 30 int a , b; 31 scanf("%d%d",&a,&b); 32 edges[i].from = a; 33 edges[i].to = b; 34 add_edge(a,b); 35 deg[b]++; 36 } 37 l = r = 0; 38 for(int i = 1; i <= n; i++){ 39 if(!deg[i]){ 40 q[r++] = i; 41 } 42 } 43 44 while(l<r){ 45 int u = q[l++]; 46 if(l==r){ 47 out[u] = n - r; 48 }else if(l+1 == r){ 49 int v = q[l]; 50 int flag = 1; 51 for(int i = head[v]; i!=-1; i = Next[i]){ 52 int vv = to[i]; 53 if(deg[vv] == 1){ 54 flag = 0; 55 break; 56 } 57 } 58 if(!flag) 59 out[u] = -n; 60 else 61 out[u] = n - r; 62 }else 63 out[u] = -n; 64 65 for(int i = head[u]; i!=-1; i = Next[i]){ 66 int v = to[i]; 67 deg[v]--; 68 if(!deg[v]) 69 q[r++] = v; 70 } 71 } 72 init(); 73 for(int i = 1; i <= m; i++){ 74 add_edge(edges[i].to,edges[i].from); 75 deg[edges[i].from]++; 76 } 77 l=r=0; 78 for(int i = 1; i <= n; i++){ 79 if(!deg[i]){ 80 q[r++] = i; 81 } 82 } 83 while(l<r){ 84 int u = q[l++]; 85 if(l==r){ 86 in[u] = n - r; 87 }else if(l+1 == r){ 88 int v = q[l]; 89 int flag = 1; 90 for(int i = head[v]; i != -1; i = Next[i]){ 91 int vv = to[i]; 92 if(deg[vv] == 1){ 93 flag = 0; 94 break; 95 } 96 } 97 if(!flag) 98 in[u] = -n; 99 else 100 in[u] = n - r; 101 }else 102 in[u] = -n; 103 for(int i = head[u]; i != -1; i = Next[i]){ 104 int vv = to[i]; 105 deg[vv] --; 106 if(!deg[vv]) 107 q[r++] = vv; 108 } 109 } 110 int ans = 0; 111 for(int i = 1; i <= n; i++){ 112 // printf("%d %d\n",in[i],out[i]); 113 if(in[i] + out[i] >= n-2){ 114 ans++; 115 } 116 } 117 printf("%d\n",ans); 118 return 0; 119 }