atcoder regular 175 题解 A-C D还未解决
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 */