Yet Another Dividing into Teams

 

有一个长度为n的序列a1,a2...an,将他们分为若干组,使得每一组没有两个数的差为1,使分的组数尽可能少。

 

思路:
将数组排序之后从前往后遍历,如果出现了两个数的差值为1 那么就得分两组  否则 一组

 

 1 #include <math.h>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <string>
 7 #include <string.h>
 8 #include <vector>
 9 #include <map>
10 #include <stack>
11 #include <set>
12 //#include <random>
13  
14 #define LL long long
15 #define INF 0x3f3f3f3f
16 #define ls nod<<1
17 #define rs (nod<<1)+1
18 const int maxn = 2e5 + 10;
19 const double eps = 1e-9;
20  
21 int arr[maxn];
22 int main() {
23     int T;
24     scanf("%d",&T);
25     while (T--) {
26         int n;
27         scanf("%d",&n);
28         for (int i=1;i<=n;i++) {
29             scanf("%d",&arr[i]);
30         }
31         std::sort(arr+1,arr+1+n);
32         if (n == 1) {
33             printf("1\n");
34             continue;
35         }
36         bool flag = false;
37         for (int i=2;i<=n;i++) {
38             if (arr[i] - arr[i-1] <= 1) {
39                 flag = true;
40             }
41         }
42         if (flag) {
43             printf("2\n");
44         }
45         else
46             printf("1\n");
47     }
48     return 0;
49 }

 

B1、B2 - Books Exchange (easy version)

 

 

有n个孩子,每个孩子都在读一本独特的书。在任何一天结束时,第i个孩子将把他的书交给第pi个孩子(如果i = pi,则该孩子将把他的书交给他自己)。保证pi的所有值都是从1到n的不同整数(即p是一个排列)。序列p每天都不变化,它是固定的。

例如,如果n = 6且p = [4,6,1,3,5,2],则在第一天结束时,第一个孩子的书将属于第四个孩子,第二个孩子-第二个孩子将属于第六个孩子,依此类推。在第二天结束时,第一个孩子的书将属于第三个孩子,第二个孩子将属于第二个孩子,依此类推。

您的任务是确定从1到n的每个i,第i个孩子的书第一次返还给他的天数。

考虑以下示例:p = [5,1,2,4,3]。第一个孩子的书将传递给以下孩子:

第一天之后,它将属于第五个孩子, 第2天之后,它将属于第3个孩子, 第三天之后,它将属于第二个孩子, 在第4天之后,它将属于第一个孩子。 因此,第四天之后,第一个孩子的书将归还其所有者。第四天的书将在整整一天后第一次归还给他。

您必须回答q个独立查询。

输入

输入的第一行包含一个整数q(1≤q≤200)-查询数。然后q查询。

查询的第一行包含一个整数n(1≤n≤200)-查询中孩子的数量。查询的第二行包含n个整数p1,p2,…,pn(1≤pi≤n,所有pi都是唯一的,即p是排列),其中pi是将得到第i个书的孩子小子

输出

对于每个查询,在其上打印答案:n个整数a1,a2,…,an,其中ai是该查询中第i个孩子的书第一次还给他的天数。

 

以样例为例

 

 

会发现 环上的每个开始到第一次回到自己手中的天数都是一样的 

 

 1 #include <math.h>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <string>
 7 #include <string.h>
 8 #include <vector>
 9 #include <map>
10 #include <stack>
11 #include <set>
12 //#include <random>
13  
14 #define LL long long
15 #define INF 0x3f3f3f3f
16 #define ls nod<<1
17 #define rs (nod<<1)+1
18 const int maxn = 2e5 + 10;
19 const double eps = 1e-9;
20  
21 int fa[maxn],arr[maxn];
22 int cnt;
23 void dfs(int i,int j) {
24     cnt++;
25     if (arr[i] == j) {
26         fa[i] = cnt;
27         return ;
28     }
29     else {
30         dfs(arr[i],j);
31         fa[i] = cnt;
32     }
33 }
34 int main() {
35     int T;
36     scanf("%d",&T);
37     while (T--) {
38         int n;
39         scanf("%d",&n);
40         for (int i=1;i<=n;i++) {
41             scanf("%d",&arr[i]);
42             fa[i] = 0;
43         }
44         for (int i=1;i<=n;i++) {
45             if (fa[i] == 0) {
46                 cnt = 0;
47                 dfs(i,i);
48             }
49         }
50         for (int i=1;i<=n;i++) {
51             printf("%d ",fa[i]);
52         }
53         printf("\n");
54     }
55     return 0;
56 }

 

C1、C2 Good Numbers (hard version)

现在给出一个定义:Good Number(下文以好数代替),好数是指可以变成33的不同次幂的加和的数

例如:

3030 是好数 30=3^3+3^130=33+31

11 是好数 1=3^01=30

1212 是好数 12=3^2+3^112=32+31

22 不是好数,因为2=3^0+3^02=30+30,不符合不同次幂的条件

1919 不是好数,例如19=3^2+3^2+3^0=3^2+3^1+3^1+3^1+3^019=32+32+30=32+31+31+31+30,不符合不同次幂的条件

2020不是好数,同理不符合不同次幂的条件,无法把2020分为33的不同次幂的加和

现在给你一些正整数nn,对于每个nn请你给出一个最小的mm满足:①mm是好数 ②n≤mnm

输入格式

输入第一行为一个正整数q(1≤q≤500)q(1q500),表示有qq个样例

然后有qq行,每行一个正整数n(1≤n≤10^4)n(1n104)

输出格式

对于每个nnn,输出最小的mm满足:①mm是好数 ②n≤mnm。每个输出占一行

 

思路:

转化成三进制来看。其实就是判断有没有出现2 ,如果没有那就输出它自己     如果出现了就往前找

感谢机房大佬魏队的思路

  1 #include <math.h>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <string>
  7 #include <string.h>
  8 #include <vector>
  9 #include <map>
 10 #include <stack>
 11 #include <set>
 12 //#include <random>
 13  
 14 #define LL long long
 15 #define INF 0x3f3f3f3f
 16 #define ls nod<<1
 17 #define rs (nod<<1)+1
 18 const int maxn = 2e5 + 10;
 19 const double eps = 1e-9;
 20  
 21 LL arr[40] = {1,3,9,27,81,243,729,2187,6561,19683,59049,177147,531441,1594323,4782969,14348907,43046721,129140163,387420489,1162261467,3486784401,10460353203,31381059609,94143178827,282429536481,847288609443,2541865828329,7625597484987,22876792454961,68630377364883,205891132094649,617673396283947,1853020188851841,5559060566555523,16677181699666569,50031545098999707,150094635296999121,450283905890997363,1350851717672992089,4052555153018976267};
 22 int vis[20] = {0};
 23 LL bit[110];
 24  
 25  
 26 LL mul(LL a,LL b)
 27 {
 28     LL sum = 1;
 29     while (b>0)
 30     {
 31         if (b%2==1) // b是奇数
 32         {
 33             sum = (a*sum);
 34         }
 35         a = (a*a) ;
 36         b = b/2;
 37     }
 38     return sum;
 39 }
 40  
 41 LL binarySearch(LL a[],LL n,LL key)
 42 {
 43     LL left = 0;
 44     LL right = n-1;
 45     while (left <= right )
 46     {
 47         LL mid = (left + right) / 2;
 48         if (a[mid] > key)
 49             right = mid - 1;
 50         else if (a[mid] <= key)
 51             left = mid + 1;
 52     }
 53     if (a[right] <= key && !vis[right])
 54         return right;
 55     if (a[right] <= key) {
 56         while (vis[right]) {
 57             right--;
 58         }
 59         return right;
 60     }
 61     return right;
 62 }
 63  
 64 int check(LL k) {
 65     memset(vis,0, sizeof(vis));
 66     while (k) {
 67         LL idex = binarySearch(arr, 40, k);
 68         if (idex >= 0) {
 69             vis[idex] = 1;
 70             k -= arr[idex];
 71         }
 72         else {
 73             return 0;
 74         }
 75     }
 76     return 1;
 77 }
 78  
 79  
 80 int main() {
 81     int T;
 82     scanf("%d",&T);
 83     while (T--) {
 84         LL n;
 85         scanf("%lld",&n);
 86         LL nn = n;
 87         LL sum = 0;
 88         int tot = 0;
 89         while (n) {
 90             bit[++tot] = n % 3;
 91             n /= 3;
 92         }
 93         LL i;
 94         for (i=tot;i>=1;i--) {
 95             if (bit[i] == 2) {
 96                 break;
 97             }
 98         }
 99         if (!i) {
100             printf("%lld\n",nn);
101         }
102         else {
103             i++;
104             for (;;i++) {
105                 if (bit[i] == 0 || i > tot) {
106                     bit[i] = 1;
107                     break;
108                 }
109             }
110             if (i > tot)
111                 sum += mul(3,i-1);
112             for (;i<=tot;i++) {
113                 if (bit[i] == 1) {
114                     sum += mul(3,i-1);
115                 }
116             }
117             printf("%lld\n",sum);
118         }
119     }
120     return 0;
121 }

 

D1、D2 Too Many Segments 

 

给予nn条线段,这些线段可以有重叠部分甚至完全重叠在一起。第ii条线段[l_i,r_i](l_i≤r_i)[li,ri](liri)覆盖了所有整数点jj满足l_i≤j≤r_ilijri

如果一个整数点被超过kk条线段覆盖,那么就称之为bad point(下文以坏点代替)

你的任务是去掉最少的线段使得没有坏点的存在

输入格式

输入第一行是两个正整数,nn和kk(1≤k≤n≤2*10^5)(1kn2105)

然后有nn行,每行两个正整数,其中的第ii行表示第ii条线段的两个端点l_ilir_iri(1≤l_i≤r_i≤2*10^5)(1liri2105)

输出格式

输出的第一行为一个整数m(0≤m≤n)m(0mn),表示最少去掉多少条线段可以不再存在坏点

第二行输出mm个不同的正整数p_1,p_2,…p_m(1≤p_i≤n)p1,p2,pm(1pin)表示你移除了的线段的编号。如果有不止一个答案,可以输出任意一个满足条件的答案。

 

思路:

将右端点进行排序,然后我们从左端点开始取。并采取 set 进行维护,如果超过了 k ,那么直接删去最后一个就可以了,因为它是最长的!

这题同样感谢机房大佬魏队给思路

 1 #include <math.h>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <string>
 7 #include <string.h>
 8 #include <vector>
 9 #include <map>
10 #include <stack>
11 #include <set>
12 //#include <random>
13  
14 #define LL long long
15 #define INF 0x3f3f3f3f
16 #define ls nod<<1
17 #define rs (nod<<1)+1
18 const int maxn = 2e5 + 10;
19 const double eps = 1e-9;
20  
21 struct Node {
22     int y;
23     int idex;
24 };
25  
26 bool operator<(Node a,Node b) {
27     if (a.y != b.y)
28         return a.y < b.y;
29     else
30         return a.idex < b.idex;
31 }
32  
33 std::vector<Node> g[maxn];
34 std::vector<int> out;
35  
36 int main() {
37     int n,k;
38     scanf("%d%d",&n,&k);
39     for (int i=1;i<=n;i++) {
40         int x,y;
41         scanf("%d%d",&x,&y);
42         Node a;
43         a.y = y;
44         a.idex = i;
45         g[x].push_back(a);
46     }
47     std::set<Node> st;
48     for (int i=1;i<maxn;i++) {
49         while (st.size() && (*st.begin()).y < i)
50             st.erase(*st.begin());
51         for (int j=0;j<g[i].size();j++) {
52             st.insert(g[i][j]);
53         }
54         while (st.size() > k) {
55             out.push_back((*st.rbegin()).idex);
56             st.erase(*st.rbegin());
57         }
58     }
59     int len = out.size();
60     printf("%d\n",len);
61     for (int i=0;i<len;i++) {
62         printf("%d ",out[i]);
63     }
64     printf("\n");
65     return 0;
66 }

 

E - By Elevator or Stairs?

思路:

***DP

dp[i][0] 代表坐电梯,dp[i][1] 代表走楼梯

转移方程:

dp[i][0] = min(dp[i][0] + b[i-1],dp[i][1] + c + b[i-1])

dp[i][1] = min(dp[i-1][0],dp[i-1][1]) + a[i-1]

 

 1 #include <math.h>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <string>
 7 #include <string.h>
 8 #include <vector>
 9 #include <map>
10 #include <stack>
11 #include <set>
12 //#include <random>
13 
14 #define LL long long
15 #define INF 0x3f3f3f3f
16 #define ls nod<<1
17 #define rs (nod<<1)+1
18 const int maxn = 2e5 + 10;
19 const double eps = 1e-9;
20 
21 int n,c;
22 int a[maxn],b[maxn],dp[maxn][2];
23 
24 int main() {
25     scanf("%d%d",&n,&c);
26     for (int i=1;i<n;i++) {
27         scanf("%d",&a[i]);
28     }
29     for (int i=1;i<n;i++) {
30         scanf("%d",&b[i]);
31     }
32     dp[1][0] = c;
33     dp[1][1] = 0;
34     for (int i=2;i<=n;i++) {
35         dp[i][0] = std::min(dp[i-1][0] + b[i-1], dp[i-1][1] + c + b[i-1]);
36         dp[i][1] = std::min(dp[i-1][0], dp[i-1][1]) + a[i-1];
37     }
38     for (int i=1;i<n;i++) {
39         printf("%d ",std::min(dp[i][0],dp[i][1]));
40     }
41     printf("%d\n",std::min(dp[n][0],dp[n][1]));
42     return 0;
43 }