A
要么所有人全部做左边的筷子,要么全部右边的筷子。依次处理。
大家按照顺序拿筷子,如果成立,当前的人,所需方向的筷子肯定没拿。如果所需方向的反方向的筷子被拿了,就结果*2(第一选择方向可以任选);反而,肯定要求第一选择方向是所需方向,就结果*1。
1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <cmath>
5 #include <cstdbool>
6 #include <string>
7 #include <algorithm>
8 #include <iostream>
9 #include <sstream>
10 #include <ctime>
11 #include <stack>
12 #include <vector>
13 #include <queue>
14 #include <set>
15 #include <map>
16 using namespace std;
17 #define ll long long
18 #define ull unsigned long long
19
20
21 const ll mod=998244353;
22
23 const double eps_1=1e-5;
24 const double eps_2=1e-10;
25
26 const int maxn=2e5+10;
27
28 bool vis[maxn];
29 char str[maxn];
30 int n,fx,a[maxn];
31 ll result=0;
32
33 void handle()
34 {
35 int i,d,left,right,mode;
36 ll ans=1;
37
38 for (i=1;i<=n;i++)
39 {
40 d=a[i];
41
42 left=d-1;
43 if (left==0)
44 left=n;
45 right=d+1;
46 if (right==n+1)
47 right=1;
48
49 if (str[d]=='L')
50 mode=1;
51 else if (str[d]=='R')
52 mode=2;
53 else
54 mode=0;
55
56 if (fx==1)
57 {
58 if (!vis[right] && mode==2)
59 return;
60 if (vis[right] && mode==0)
61 ans=ans*2%mod;
62 }
63 else
64 {
65 if (!vis[left] && mode==1)
66 return;
67 if (vis[left] && mode==0)
68 ans=ans*2%mod;
69 }
70 vis[d]=1;
71 }
72
73 result=(result+ans)%mod;
74 }
75
76 int main()
77 {
78 int i;
79 scanf("%d",&n);
80 for (i=1;i<=n;i++)
81 scanf("%d",&a[i]);
82 scanf("%s",str+1);
83
84 for (fx=0;fx<=1;fx++)
85 {
86 memset(vis,0,sizeof(vis));
87 handle();
88 }
89
90 printf("%lld", result);
91
92 return 0;
93 }
B
左括号,右括号数目= x,y
1. abs(x-y)/2,肯定就是修改的(->) 、 )->( 的数目。如果是)->(,一开始把“最左边”的这些')'改成’('。
2. (->) 、 )->( 花费为B,也可以花费为2*A的方式解决
3. 从左到右,记录 '(' - ')' 的数目,找出有')‘,使得 '(' - ')' = -1的情况,这时候需要B/2A了。')‘->'('后,'(' - ')'变为1。记录最少需要B/2A的次数。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdbool>
#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <ctime>
#include <stack>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define ll long long
#define ull unsigned long long
const ll mod_1=1e9+7;
const ll mod_2=998244353;
const double eps_1=1e-5;
const double eps_2=1e-10;
const int maxn=1e6+10;
char str[maxn];
int main()
{
int n,len,i;
ll cha=0,jia_cnt=0,cnt_lower_zero=0,a,b;
//ll result=0;
scanf("%d%lld%lld",&n,&a,&b);
scanf("%s",str);
len=strlen(str);
for (i=0;i<len;i++)
if (str[i]=='(')
cha++;
else
cha--;
if (cha<0)
jia_cnt=abs(cha);
cha=abs(cha)/2;
for (i=0;i<len;i++)
{
if (str[i]==')')
jia_cnt--;
else
jia_cnt++;
if (jia_cnt<0)
{
jia_cnt=1;
cnt_lower_zero++;
}
}
if (a>b*2)
printf("%lld",(cha+cnt_lower_zero*2) *b );
else
printf("%lld",cha*b + cnt_lower_zero*a );
return 0;
}
/*
(((((((((
)))))
3 2 2
((((((
3 10 2
((((((
3 2 10
((((((
3 2 2
))))))
3 2 10
))))))
3 2 10
)))(((
3 10 2
)))(((
3 2 2
)))(((
*/
C
遇到这种题很头疼,很容易找不到错误的地方,制造不出可以找到错误的样例。
这种题目应该先多制造几个样例,然后把一些条理理清楚了再写会比较好
官方题解看着有点晕,也看到写得特别短的代码,有点不理解……
我的是,把这些分为[l1,r1] [l2,r2] [l3,r3] ... [lk,rk]的区间,它们互不交集。然后区间有升有降。
如果l_{i-1} -> l_{i} -> l_{i+1} 是降、升的趋势,那么这个区间的数值应该选择r_{i},还有最左边和最右边的区间要做特殊处理,其它都选择l_{i}。
对于一个区间,它相对于上个区间是升的话,然后这个区间最左边的几个数值可以往上个区间那个靠,这是为了让字典序最小,只要满足条件即可。
同理,对于一个区间,它相对于下个区间是降的话,然后这个区间最右边的几个数值可以往下个区间那个靠,这是为了让字典序最小,只要满足条件即可。
1 /*
2 1 制造比较小的随机数据
3 10以内的
4 2 然后用std程序跑结果
5 */
6
7 #include <cstdio>
8 #include <cstdlib>
9 #include <cstring>
10 #include <cmath>
11 #include <cstdbool>
12 #include <string>
13 #include <algorithm>
14 #include <iostream>
15 #include <sstream>
16 #include <ctime>
17 #include <stack>
18 #include <vector>
19 #include <queue>
20 #include <set>
21 #include <map>
22 using namespace std;
23
24 const double eps_1=1e-5;
25 const double eps_2=1e-10;
26
27 const int maxn=5e5+10;
28
29
30
31
32 int l[maxn],r[maxn],v[maxn],result[maxn];
33 int ql[maxn],qr[maxn],range[maxn];
34
35 int main()
36 {
37 int inf=1e9+10;
38 int n,i,j,k,o,ll=-inf,rr=inf,cnt=1,temp;
39 range[0]=0;
40 scanf("%d",&n);
41 for (i=1;i<=n;i++)
42 {
43 scanf("%d%d",&l[i],&r[i]);
44
45 if (r[i]<ll || l[i]>rr)
46 {
47 range[cnt]=i-1;
48 ql[cnt]=ll;
49 qr[cnt]=rr;
50
51 ll=l[i];
52 rr=r[i];
53 cnt++;
54 }
55
56 ll=max(ll, l[i]);
57 rr=min(rr, r[i]);
58 }
59
60 ql[cnt]=ll;
61 qr[cnt]=rr;
62 range[cnt]=n;
63
64
65
66
67 for (i=1;i<=cnt;i++)
68 v[i]=ql[i];
69
70 if (cnt!=1)
71 {
72
73 i=1;
74 while (i<cnt)
75 {
76 if (i<cnt && ql[i]>ql[i+1])
77 {
78 while (ql[i]>ql[i+1])
79 i++;
80 if (i!=cnt)
81 v[i]=qr[i];
82 }
83 i++;
84 }
85
86 if (ql[1]<ql[2])
87 v[1]=qr[1];
88
89 if (ql[cnt-1]>ql[cnt])
90 v[cnt]=qr[cnt];
91 }
92
93
94 for (i=1 ;i<=cnt;i++)
95 {
96 if (i!=1 && v[i]>v[i-1])
97 {
98 temp = l[ range[i-1]+1 ];
99 for (o=range[i-1]+1 ; o<=range[i] ; o++)
100 {
101 if (l[o]>temp)
102 temp=l[o];
103 if (temp==v[i])
104 break;
105 result[o]=temp;
106 }
107 }
108 else
109 o=range[i-1]+1;
110
111 if (i!=cnt && v[i]>v[i+1])
112 {
113 temp = v[i+1];
114 for (k=range[i] ; k>=o ; k--)
115 {
116 if (l[k]>temp)
117 temp=l[k];
118 if (temp==v[i])
119 break;
120 result[k]=temp;
121 }
122 }
123 else
124 k=range[i];
125
126 for (j=o ; j<=k ; j++)
127 result[j]=v[i];
128
129 }
130
131 for (i=1;i<=n;i++)
132 {
133 printf("%d",result[i]);
134 if (i!=n)
135 printf(" ");
136 }
137
138 return 0;
139 }
140 /*
141 15
142 5 29
143 9 28
144 15 19
145 4 26
146 7 23
147 10 13
148 12 25
149 3 11
150 6 17
151 1 21
152 24 27
153 2 8
154 14 18
155 20 22
156 16 30
157
158
159
160 15 15 15 12 12 12 12 11 11 11 24 8 14 20 20
161
162
163
164
165
166 5
167 50 60
168 40 50
169 30 40
170 20 30
171 10 20
172
173 5
174 10 20
175 20 30
176 30 40
177 40 50
178 50 60
179
180 2
181 10 30
182 40 60
183
184 2
185 40 60
186 10 30
187
188 5
189 100 200
190 300 400
191 500 600
192 50 70
193 20 40
194
195 */
1 /*
2 1 制造比较小的随机数据
3 10以内的
4 2 然后用std程序跑结果
5 */
6
7 #include <cstdio>
8 #include <cstdlib>
9 #include <cstring>
10 #include <cmath>
11 #include <cstdbool>
12 #include <string>
13 #include <algorithm>
14 #include <iostream>
15 #include <sstream>
16 #include <ctime>
17 #include <stack>
18 #include <vector>
19 #include <queue>
20 #include <set>
21 #include <map>
22 using namespace std;
23
24 const double eps_1=1e-5;
25 const double eps_2=1e-10;
26
27 const int maxn=5e5+10;
28
29
30 int l[maxn],r[maxn],v[maxn],result[maxn];
31 int ql[maxn],qr[maxn],range[maxn];
32
33 int main()
34 {
35 int inf=1e9+10;
36 int n,i,j,ll=-inf,rr=inf,cnt=0,temp;
37 range[0]=0;
38 scanf("%d",&n);
39 for (i=1;i<=n;i++)
40 {
41 scanf("%d%d",&l[i],&r[i]);
42
43 if (r[i]<ll || l[i]>rr)
44 {
45 ++cnt;
46 range[cnt]=i-1;
47 ql[cnt]=ll;
48 qr[cnt]=rr;
49
50 ll=-inf,rr=inf;
51 }
52
53 ll=max(ll, l[i]);
54 rr=min(rr, r[i]);
55 }
56
57 ++cnt;
58 range[cnt]=n;
59 ql[cnt]=ll;
60 qr[cnt]=rr;
61
62
63 for (i=1;i<=cnt;i++)
64 if (cnt!=1 && ((i==1 || ql[i]<ql[i-1]) && (i==cnt || ql[i]<ql[i+1])))
65 v[i]=qr[i];
66 else
67 v[i]=ql[i];
68 j=1;
69 for (i=1;i<=n;i++)
70 {
71 result[i]=v[j];
72 if (j!=cnt && i==range[j])
73 j++;
74 }
75
76 for (i=1;i<=cnt;i++)
77 {
78 //asc
79 if (i!=1 && v[i]>v[i-1])
80 {
81 j=range[i-1]+1;
82 temp = v[i-1];
83 while (temp<ql[i])
84 {
85 temp=max(temp,l[j]);
86 result[j]=temp;
87 j++;
88 }
89 }
90
91 //des
92 if (i!=cnt && v[i]>v[i+1])
93 {
94 j=range[i];
95 temp=v[i+1];
96 while (temp<ql[i])
97 {
98 temp=max(temp,l[j]);
99 result[j]=temp;
100 j--;
101 }
102 }
103 }
104
105 for (i=1;i<=n;i++)
106 {
107 printf("%d",result[i]);
108 if (i!=n)
109 printf(" ");
110 }
111
112 return 0;
113 }
114 /*
115 15
116 5 29
117 9 28
118 15 19
119 4 26
120 7 23
121 10 13
122 12 25
123 3 11
124 6 17
125 1 21
126 24 27
127 2 8
128 14 18
129 20 22
130 16 30
131
132
133
134 15 15 15 12 12 12 12 11 11 11 24 8 14 20 20
135
136
137
138
139
140 5
141 50 60
142 40 50
143 30 40
144 20 30
145 10 20
146
147 5
148 10 20
149 20 30
150 30 40
151 40 50
152 50 60
153
154 2
155 10 30
156 40 60
157
158 2
159 40 60
160 10 30
161
162 5
163 100 200
164 300 400
165 500 600
166 50 70
167 20 40
168
169 */
把样例里的数值离散化,方便看得清
1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <cmath>
5 #include <cstdbool>
6 #include <string>
7 #include <algorithm>
8 #include <iostream>
9 #include <sstream>
10 #include <ctime>
11 #include <stack>
12 #include <vector>
13 #include <queue>
14 #include <set>
15 #include <map>
16 using namespace std;
17 #define ll long long
18 #define ull unsigned long long
19
20 const ll mod_1=1e9+7;
21 const ll mod_2=998244353;
22
23 const double eps_1=1e-5;
24 const double eps_2=1e-10;
25
26 const int maxn=30+10;
27
28
29 int a[maxn],b[maxn],c[maxn],r[maxn];
30 map<int,int> map_1;
31
32
33 int main()
34 {
35 int n,i,j=0;
36 scanf("%d",&n);
37 for (i=1;i<=n;i++)
38 {
39 scanf("%d%d",&a[i],&b[i]);
40 c[i*2-1]=a[i];
41 c[i*2]=b[i];
42 }
43 for (i=1;i<=n;i++)
44 scanf("%d",&r[i]);
45 sort(c+1,c+2*n+1);
46 c[0]=-1;
47 for (i=1;i<=2*n;i++)
48 if (c[i]!=c[i-1])
49 {
50 j++;
51 map_1[ c[i] ] = j;
52 }
53
54 for (i=1;i<=n;i++)
55 printf("%d %d\n",map_1[ a[i] ], map_1[ b[i] ]);
56 printf("\n\n\n");
57 for (i=1;i<=n;i++)
58 printf("%d ",map_1[ r[i] ]);
59
60 return 0;
61 }
62 /*
63 5 29
64 9 28
65 15 19
66 4 26
67 7 23
68 10 13
69 12 25
70 3 11
71 6 17
72 1 21
73 24 27
74 2 8
75 14 18
76 20 22
77 16 30
78
79
80
81
82 5 29
83 9 28
84 15 19
85 4 26
86 7 23
87 10 13
88 12 25
89 3 11
90 6 17
91 1 21
92 24 27
93 2 8
94 14 18
95 20 22
96 16 30
97
98
99
100 15 15 15 12 12 12 12 11 11 11 24 8 14 20 20
101 */
创建小的数据
1 /*
2 10以内数据
3 */
4 #include <cstdio>
5 #include <cstdlib>
6 #include <cstring>
7 #include <cmath>
8 #include <cstdbool>
9 #include <string>
10 #include <algorithm>
11 #include <iostream>
12 #include <sstream>
13 #include <ctime>
14 #include <stack>
15 #include <vector>
16 #include <queue>
17 #include <set>
18 #include <map>
19 using namespace std;
20 #define ll long long
21 #define ull unsigned long long
22
23 const ll mod_1=1e9+7;
24 const ll mod_2=998244353;
25
26 const double eps_1=1e-5;
27 const double eps_2=1e-10;
28
29 const int maxn=2e5+10;
30
31
32
33
34
35
36 int main()
37 {
38 int n=30,range=30,i,x,y;
39 srand((int)time(0));
40 printf("%d\n",n);
41
42 for (i=1;i<=n;i++)
43 {
44 x=rand()%range;
45 y=rand()%range;
46 if (x>y)
47 swap(x,y);
48 printf("%d %d\n",x,y);
49 }
50
51
52 return 0;
53 }
暴力用程序获取小数据的输出结果
比如数据l_i,r_i在1-x范围内
然后结果可以是(r_i - l_i + 1) ^n种,然后在最小化的情况下,最小序列的输出
复杂度(r_i - l_i + 1) ^n
9个l_i-r_i范围为1-10的数据
12个l_i-r_i范围为1-5的数据
17个l_i-r_i范围为1-3的数据
看着也勉强还行
如果真要到这种地步的话
如果是赛后,对着test case或者是用别人的std代码跑一些样例出来
D
往子树都整体,DP这些角度想
用的是官方题解的方法
对于K,最小的是N
然后要想办法,增加K的数值
设置这个点都小于/大于它的子树里面的点,K分别增加子树点数目-1,0。
然后设置哪个点的数值为多少。dfs处理
这样写有问题,看某个下面的样例
1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <cmath>
5 #include <cstdbool>
6 #include <string>
7 #include <algorithm>
8 #include <iostream>
9 #include <sstream>
10 #include <ctime>
11 #include <stack>
12 #include <vector>
13 #include <queue>
14 #include <set>
15 #include <map>
16 using namespace std;
17 #define LL long long
18 #define ULL unsigned long long
19
20 const LL mod_1=1e9+7;
21 const LL mod_2=998244353;
22
23 const double eps_1=1e-5;
24 const double eps_2=1e-10;
25
26 const int maxn=2e5+10;
27
28 LL value;
29
30 vector<int> adj[maxn], child[maxn];
31 bool hap[maxn];
32 int subtree[maxn], use[maxn], ind[maxn];
33
34 pair<int,int> v[maxn];
35
36 void find_child(int d)
37 {
38 subtree[d]=1;
39
40 hap[d]=1;
41 for (auto chi:adj[d])
42 if (!hap[chi])
43 {
44 child[d].push_back(chi);
45 find_child(chi);
46 subtree[d] += subtree[chi];
47 }
48 }
49
50 void dfs(int d, int l, int r)
51 {
52 int ind_begin;
53 if (use[d]==1)
54 ind[d]=l, ind_begin=l+1;
55 else
56 ind[d]=r, ind_begin=l;
57
58 for (auto chi:child[d])
59 {
60 dfs(chi,ind_begin, ind_begin+subtree[chi]-1);
61 ind_begin+=subtree[chi];
62 }
63
64 }
65
66 int main()
67 {
68 int n,i,x,y;
69 LL max_value=0;
70 memset(hap,0,sizeof(hap));
71 cin>>n>>value;
72 for (i=1;i<n;i++)
73 {
74 cin>>x>>y;
75 adj[x].push_back(y);
76 adj[y].push_back(x);
77 }
78
79 find_child(1);
80
81 for (i=1;i<=n;i++)
82 max_value += subtree[i];
83
84 if (value<n || n>max_value)
85 {
86 cout<<"No";
87 return 0;
88 }
89
90 for (i=1;i<=n;i++)
91 v[i] = {subtree[i]-1, i};
92 sort(v+1, v+n+1);
93 value-=n;
94
95 for (i=n;i>=1;i--)
96 if (value>=v[i].first)
97 {
98 use[ v[i].second ]=1;
99 value-=v[i].first;
100 }
101 else
102 use[ v[i].second ]=-1;
103
104
105 dfs(1,1,n);
106
107 cout<<"Yes"<<endl;
108 for (i=1;i<=n;i++)
109 {
110 cout<<ind[i];
111 if (i==n)
112 cout<<endl;
113 else
114 cout<<" ";
115 }
116
117 return 0;
118 }
119 /*
120 5 4
121 1 2
122 2 3
123 3 4
124 4 5
125
126 ===
127
128 5 5
129 1 2
130 2 3
131 3 4
132 4 5
133
134 ===
135
136 5 6
137 1 2
138 2 3
139 3 4
140 4 5
141
142 ===
143
144 5 7
145 1 2
146 2 3
147 3 4
148 4 5
149
150 ===
151
152 5 15
153 1 2
154 2 3
155 3 4
156 4 5
157
158 ===
159
160 5 16
161 1 2
162 2 3
163 3 4
164 4 5
165
166 ===
167
168 5 5
169 1 2
170 1 3
171 1 4
172 1 5
173
174 ===
175
176 有问题
177 5 6
178 1 2
179 1 3
180 1 4
181 1 5
182
183 ===
184
185 5 9
186 1 2
187 1 3
188 1 4
189 1 5
190 */
看到某位大佬的代码很简洁
1 //#pragma GCC optimize("Ofast")
2 //#pragma GCC target("avx,avx2,fma")
3 //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,sse4a,avx,avx2,popcnt,tune=native")
4 #include <iostream>
5 #include <cstdio>
6 #include <cstdlib>
7 #include <algorithm>
8 #include <cmath>
9 #include <vector>
10 #include <set>
11 #include <map>
12 #include <unordered_set>
13 #include <unordered_map>
14 #include <queue>
15 #include <ctime>
16 #include <cassert>
17 #include <complex>
18 #include <string>
19 #include <cstring>
20 #include <chrono>
21 #include <random>
22 #include <bitset>
23 #include <array>
24 #include <climits>
25 using namespace std;
26
27 #ifdef LOCAL
28 #define eprintf(...) {fprintf(stderr, __VA_ARGS__);fflush(stderr);}
29 #else
30 #define eprintf(...) 42
31 #endif
32
33 using ll = long long;
34 using ld = long double;
35 using uint = unsigned int;
36 using ull = unsigned long long;
37 using pii = pair<int, int>;
38 using pli = pair<ll, int>;
39 using pll = pair<ll, ll>;
40 mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
41 ll myRand(ll B) {
42 return (ull)rng() % B;
43 }
44
45 #define mp make_pair
46 #define all(x) (x).begin(),(x).end()
47
48 clock_t startTime;
49 double getCurrentTime() {
50 return (double)(clock() - startTime) / CLOCKS_PER_SEC;
51 }
52
53 ll floor_div(ll x, ll y) {
54 assert(y != 0);
55 if (y < 0) {
56 y = -y;
57 x = -x;
58 }
59 if (x >= 0) return x / y;
60 return (x + 1) / y - 1;
61 }
62 ll ceil_div(ll x, ll y) {
63 assert(y != 0);
64 if (y < 0) {
65 y = -y;
66 x = -x;
67 }
68 if (x <= 0) return x / y;
69 return (x - 1) / y + 1;
70 }
71 template<typename T>
72 T sqr(T x) {
73 return x * x;
74 }
75
76 const int N = 200200;
77 vector<int> g[N];
78 int h[N];
79 int sz[N];
80 ll k;
81 int n;
82 bool bad[N];
83 pii ord[N];
84 int ans[N];
85
86 void dfs(int v, int par) {
87 sz[v] = 1;
88 for (int u : g[v]) if (u != par) {
89 h[u] = h[v] + 1;
90 dfs(u, v);
91 sz[v] += sz[u];
92 }
93 }
94
95 int main() {
96 startTime = clock();
97 // freopen("input.txt", "r", stdin);
98 // freopen("output.txt", "w", stdout);
99
100 scanf("%d%lld", &n, &k);
101 for (int i = 1; i < n; i++) {
102 int v, u;
103 scanf("%d%d", &v, &u);
104 g[v].push_back(u);
105 g[u].push_back(v);
106 }
107 dfs(1, 0);
108 if (k < n) {
109 printf("No\n");
110 return 0;
111 }
112 for (int v = 1; v <= n; v++) {
113 k -= sz[v];
114 }
115 if (k > 0) {
116 printf("No\n");
117 return 0;
118 }
119 k = -k;
120 int m = 0;
121 for (int v = 2; v <= n; v++)
122 ord[m++] = mp(sz[v], v);
123 sort(ord, ord + m);
124 reverse(ord, ord + m);
125 for (int i = 0; i < m; i++) if (ord[i].first <= k) {
126 k -= ord[i].first;
127 bad[ord[i].second] = 1;
128 }
129 assert(k == 0);
130 m = 0;
131 for (int v = 1; v <= n; v++) if (bad[v]) {
132 ord[m++] = mp(-h[v], v);
133 }
134 for (int v = 1; v <= n; v++) if (!bad[v]) {
135 ord[m++] = mp(h[v], v);
136 }
137 sort(ord, ord + m);
138 for (int i = 0; i < m; i++)
139 ans[ord[i].second] = i + 1;
140 printf("Yes\n");
141 for (int i = 1; i <= n; i++)
142 printf("%d ", ans[i]);
143 printf("\n");
144
145 return 0;
146 }
还有这个大佬,看着像另外一个风格的做法
1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 typedef long long ll;
6
7 ll n, k;
8 vector<ll> adj[200010];
9 ll a[200010];
10 ll sz[200010];
11 ll f[200010];
12 vector<pair<ll,ll>> t;
13
14 void dfs(ll x, ll p) {
15 sz[x] = 1;
16 for (auto &y : adj[x]) {
17 if (y == p) continue;
18 dfs(y, x);
19 sz[x] += sz[y];
20 }
21 if (x != 1) t.push_back({sz[x], x});
22 }
23
24 void dfs2(ll x, ll p, ll l, ll r) {
25 ll cnt = 0;
26 for (auto &y : adj[x]) {
27 if (y == p) continue;
28 if (f[y]) cnt += sz[y];
29 }
30 a[x] = l + cnt;
31 ll t1 = 0, t2 = 0;
32 for (auto &y : adj[x]) {
33 if (y == p) continue;
34 if (f[y]) {
35 dfs2(y, x, l+t1, l+t1+sz[y]-1);
36 t1 += sz[y];
37 }
38 else {
39 dfs2(y, x, l+cnt+1+t2, l+cnt+t2+sz[y]);
40 t2 += sz[y];
41 }
42 }
43 }
44
45 int main() {
46 ios_base :: sync_with_stdio(false);
47 cin.tie(NULL);
48 cin >> n >> k;
49 for (ll i=0; i<n-1; i++) {
50 ll u, v;
51 cin >> u >> v;
52 adj[u].push_back(v);
53 adj[v].push_back(u);
54 }
55 if (k < n) {
56 cout << "No\n";
57 return 0;
58 }
59 k -= n;
60 dfs(1, 0);
61 sort(t.begin(), t.end());
62 reverse(t.begin(), t.end());
63 for (ll i=0; i<n; i++) {
64 if (k >= t[i].first) {
65 f[t[i].second] = 1;
66 k -= t[i].first;
67 }
68 }
69 if (k) {
70 cout << "No\n";
71 return 0;
72 }
73 dfs2(1, 0, 1, n);
74 cout << "Yes\n";
75 for (ll i=1; i<=n; i++) {
76 cout << n - a[i] + 1 << ' ';
77 }
78 }
类似题目 ABC165_F_LIS_on_Tree
LIS,二分,当前数值修改到这个当下最长子序列对应的位置
树,dfs,当前位置,前修改,最后修改回来
1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <cmath>
5 #include <cstdbool>
6 #include <string>
7 #include <algorithm>
8 #include <iostream>
9 #include <sstream>
10 #include <ctime>
11 #include <stack>
12 #include <vector>
13 #include <queue>
14 #include <set>
15 #include <map>
16 using namespace std;
17 #define LL long long
18 #define ULL unsigned long long
19
20 const LL mod_1=1e9+7;
21 const LL mod_2=998244353;
22
23 const double eps_1=1e-5;
24 const double eps_2=1e-10;
25
26 const int maxn=2e5+10;
27
28 int a[maxn], f[maxn], result[maxn], cnt=0;
29
30 vector<int> adj[maxn], child[maxn];
31 bool hap[maxn];
32
33 void find_child(int d)
34 {
35 hap[d]=1;
36 for (auto chi:adj[d])
37 if (!hap[chi])
38 {
39 child[d].push_back(chi);
40 find_child(chi);
41 }
42 }
43
44 void dfs(int d)
45 {
46 int pre_f_ith, pre_cnt = cnt;
47
48 int ith = lower_bound(f, f+cnt, a[d]) - f;
49 pre_f_ith = f[ith];
50 f[ith] = a[d];
51 if (ith>=cnt)
52 cnt++;
53 result[d] = cnt;
54
55 for (auto chi:child[d])
56 dfs(chi);
57
58 cnt = pre_cnt;
59 f[ith] = pre_f_ith;
60 }
61
62 int main()
63 {
64 int n,i,x,y;
65 memset(hap,0,sizeof(hap));
66 scanf("%d",&n);
67 for (i=1;i<=n;i++)
68 scanf("%d",&a[i]);
69 for (i=1;i<n;i++)
70 {
71 scanf("%d%d",&x,&y);
72 adj[x].push_back(y);
73 adj[y].push_back(x);
74 }
75
76 f[0]=0;
77 find_child(1);
78 dfs(1);
79
80 for (i=1;i<=n;i++)
81 printf("%d\n",result[i]);
82
83 return 0;
84 }
85 /*
86 5
87 1 2 3 4 5
88 1 2
89 2 3
90 3 4
91 4 5
92
93
94 5
95 5 4 3 2 1
96 1 2
97 2 3
98 3 4
99 4 5
100
101 1
102 1
103
104 5
105 10 10 10 10 10
106 1 2
107 2 3
108 3 4
109 4 5
110
111
112 7
113 7 9 9 11 11 10 10
114 1 2
115 2 3
116 3 4
117 4 5
118 5 6
119 6 7
120
121 */