赞
踩
题意:给定n个字符串,求一个将他们拼接起来的方案,使得结果的字典序最小。
分析:对n个字符串排序,a在b前面的条件是ab<ba,为什么这样正反拼接是正确的呢?在S1为S2子串的情况下,我们要考虑把谁放在前面,那就比一比谁放前面更小就可以了。
代码:
不加&会超时!不加&会超时!不加&会超时!传引用传引用传引用!!!
- #include<bits/stdc++.h>
- using namespace std;
-
- const int N=2e6+6;
- int T,n,a[N];
- string s[N];
-
- int cmp(string &a, string &b)
- {
- string s1 = a + b, s2 = b + a;
- return s1 < s2;
- }
-
- int main()
- {
- cin>>n;
- for( int i=1; i<=n; ++i ) cin>>s[i];
- sort(s + 1, s + n + 1, cmp);
- for(int i = 1; i <= n; i++) cout << s[i];
- return 0;
- }
题意:给出两棵编号为1~n的树A和B,A、B树上每个节点均有一个权值,给出k个关键点的编号x1...xn,问有多少种方案使得去掉恰好一个关键点使得剩余关键点在树A上LCA的权值大于树B上LCA的权值。
分析:
需要用到一个结论——树上多个点的LCA为这多个点中DFS序最大的点和DFS序最小的点的LCA。故可以先求出所给k个关键点的DFS序,然后枚举删去哪一个。记得枚举前预处理LCA,要不然会超时。预处理其实只用求3+3次就可以了,分别为:删掉A的DFS最小(Ahead),删掉A的DFS序最大(Atail),删掉A的DFS序中间元素。
枚举每个点的时候 if-else 判断一下该点在A、B树中的地位即可。
代码:
(有点长,主要是因为A、B两棵树形态不同,所以需要分开求。)
- #include<bits/stdc++.h>
- using namespace std;
- using ll=long long;
- const int MAXN=105000;
- int N,K,x,ans=0;
- int d1,d2;
- int w1[MAXN],w2[MAXN]; //存两棵树每个点的weight
- int key[MAXN];//题目中提到的K个key number
- int ds1[MAXN],ds2[MAXN];// 存dfs序 dfs sort
- int Log2[MAXN],faA[MAXN][30],faB[MAXN][30],depA[MAXN]={0},depB[MAXN]={0};//找LCA需要的一些数组
- bool visA[MAXN]={false},visB[MAXN]={false};//找LCA需要的一些数组
- vector< vector<int> > treeA,treeB;//存树
- vector< pair<int,int> > KDS1,KDS2;//第一个数存顶点的dfs序,第二个数存顶点编号
-
- void TOinput()
- {
- for(int i=1;i<=K;i++) cin>>key[i];
- for(int i=1;i<=N;i++) cin>>w1[i];
- for(int i=2;i<=N;i++)
- {
- cin>>x;
- treeA[x].push_back(i);
- treeA[i].push_back(x);
- }
- for(int i=1;i<=N;i++) cin>>w2[i];
- for(int i=2;i<=N;i++)
- {
- cin>>x;
- treeB[x].push_back(i);
- treeB[i].push_back(x);
- }
- }
-
- void do_pre()
- {
- Log2[1] = 0;
- for (int i = 2; i <= N; ++i)
- Log2[i] = Log2[i / 2] + 1;
- }
-
- void dfsA(int cur, int fath)
- {
- if (visA[cur]) return;
-
- visA[cur] = true;
- depA[cur] = depA[fath] + 1;
- faA[cur][0] = fath;
- ds1[cur]=d1++;
-
- for (int i = 1; i <= Log2[depA[cur]]; i++) faA[cur][i] = faA[faA[cur][i - 1]][i - 1];
-
- for (int i=0; i<treeA[cur].size();i++)
- dfsA(treeA[cur][i], cur);
- }
-
-
- void dfsB(int cur, int fath)
- {
- if (visB[cur]) return;
-
- visB[cur] = true;
- depB[cur] = depB[fath] + 1;
- faB[cur][0] = fath;
- ds2[cur]=d2++;
-
- for (int i = 1; i <= Log2[depB[cur]]; i++) faB[cur][i] = faB[faB[cur][i - 1]][i - 1];
-
- for (int i=0; i<treeB[cur].size();i++)
- dfsB(treeB[cur][i], cur);
- }
-
-
- int lcaAA(int a, int b)
- {
- if (depA[a] > depA[b]) swap(a, b);
- while (depA[a] != depA[b]) b = faA[b][Log2[depA[b] - depA[a]]];
-
- if (a == b) return a;
- for (int k = Log2[depA[a]]; k >= 0; k--)
- {
- if (faA[a][k] != faA[b][k]) a = faA[a][k], b = faA[b][k];
- }
- return faA[a][0];
- }
-
- int lcaBB(int a, int b)
- {
- if (depB[a] > depB[b]) swap(a, b);
- while (depB[a] != depB[b]) b = faB[b][Log2[depB[b] - depB[a]]];
-
- if (a == b) return a;
- for (int k = Log2[depB[a]]; k >= 0; k--)
- {
- if (faB[a][k] != faB[b][k]) a = faB[a][k], b = faB[b][k];
- }
- return faB[a][0];
- }
-
- void TOdelete()
- {
- sort(KDS1.begin(),KDS1.end());
- sort(KDS2.begin(),KDS2.end());
- int Ahead=KDS1[0].second,Atail=KDS1[K-1].second,Bhead=KDS2[0].second,Btail=KDS2[K-1].second;
- int A1,A2,A3,B1,B2,B3;
- A1=lcaAA(KDS1[1].second,Atail);//头被删了
- A2=lcaAA(Ahead,KDS1[K-2].second);//尾巴被删了
- A3=lcaAA(Ahead,Atail);//删的是中间的
- B1=lcaBB(KDS2[1].second,Btail);
- B2=lcaBB(Bhead,KDS2[K-2].second);
- B3=lcaBB(Bhead,Btail);
-
- for(int i=1;i<=K;i++)
- {
- int lcaA,lcaB;
- if(key[i]==Ahead) lcaA=A1;
- if(key[i]==Atail) lcaA=A2;
- if(key[i]!=Ahead && key[i]!=Atail) lcaA=A3;
-
- if(key[i]==Bhead) lcaB=B1;
- if(key[i]==Btail) lcaB=B2;
- if(key[i]!=Bhead && key[i]!=Btail) lcaB=B3;
-
- if(w1[lcaA]>w2[lcaB]) ans++;
- }
- }
-
-
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
-
- cin>>N>>K;
- treeA.resize(N+10);
- treeB.resize(N+10);
-
- TOinput();
- do_pre();
- d1=1; d2=1;
- dfsA(1,0); for(int i=1;i<=K;i++) KDS1.push_back({ds1[key[i]],key[i]}); //把通过dfs得到的字典序存进去
- dfsB(1,0); for(int i=1;i<=K;i++) KDS2.push_back({ds2[key[i]],key[i]});
-
- TOdelete();//枚举 删去哪一个key number点
-
- cout<<ans;
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。