T1 permutation
Desprition
小 R 有 (n) 和一个 (1-n) 的排列,想求它的下一个排列(下一个排列的定义是:(1-n) 的所有全排列按字典序排好后,排在 A 后面的那个叫做 A 的下一个排列。字典序中最后一个排列的下一个排列认为是字典序中第一个排列)。
(nleq 10^5)
solution :
No next_permutation
找规律题。
首先构造一种方案,从后往前找,找到第一个 (a[i] > a[i+1]) 的数,然后把 (a[i]) 这个数设为 (a[i+1]-a[n]) 中第一个比 (a[i]) 大的数。
剩下的按从小到大顺序输出就行。
正确性 对拍请。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e5+10;
int n,last,a[N],tr[N];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
int lowbit(int x) { return x & -x; }
void chenge(int x,int val)
{
for(; x <= n; x += lowbit(x)) tr[x] += val;
}
int query(int x)
{
int res = 0;
for(; x; x -= lowbit(x)) res += tr[x];
return res;
}
int main()
{
freopen("permutation.in","r",stdin);
freopen("permutation.out","w",stdout);
n = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = n; i >= 1; i--)
{
int tmp = query(a[i]);
if(tmp != n-i)
{
last = i;
break;
}
chenge(a[i],1);
}
int tmp = a[last];
for(int i = 1; i < last; i++) printf("%d ",a[i]);
sort(a+last,a+n+1);
int x = a[lower_bound(a+last,a+n+1,tmp+1)-a];
printf("%d ",x);
for(int i = last; i <= n; i++)
{
if(a[i] == x) continue;
printf("%d ",a[i]);
}
printf("
");
fclose(stdin); fclose(stdout);
return 0;
}
T2 climb
Desprition
给你一颗 (n) 个节点的树,然后给出你每个叶子节点的经过顺序。要求以按顺序遍历这些点,并回到根节点。同时满足每条边都要被经过两次。
若没有符合条件的路线输出 (-1) 否则按顺序输出依次经过的节点的序号。
(nleq 10^5)
solution
暴力碾压正解。
首先我们的路径可以写成 (1-a[1]-a[2] ...a[n]) 的形式。
然后我们把 (a_i -a_{i+1}) 的路径拆成上行和下行两部分。
然后 一直跳父亲找到经过的节点的编号,同时统计一下每条边经过的次数就可以。
结果考试的时候数组开小了 (100pts-80pts)
正解不会。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1e5+10;
int n,m,tot,cnt,num,last,u,v,flag;
int a[N],dep[N],fa[N],siz[N],son[N],top[N],head[N],tag[N];
vector<int> path[50000];
struct node
{
int to,net;
}e[N<<1];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
void add(int x,int y)
{
e[++tot].to = y;
e[tot].net = head[x];
head[x] = tot;
}
void get_tree(int x)
{
dep[x] = dep[fa[x]] + 1; siz[x] = 1;
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(to == fa[x]) continue;
fa[to] = x;
get_tree(to);
siz[x] += siz[to];
if(siz[to] > siz[son[x]]) son[x] = to;
}
}
void dfs1(int x,int topp)
{
top[x] = topp;
if(son[x]) dfs1(son[x],topp);
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(to == fa[x] || to == son[x]) continue;
dfs1(to,to);
}
}
int lca(int x,int y)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
x = fa[top[x]];
}
return dep[x] <= dep[y] ? x : y;
}
void shuchu(int num,int x,int y)
{
while(x != y)
{
tag[x]++;
if(tag[x] > 2) {flag = 1; return; }
path[num].push_back(x);
x = fa[x];
}
path[num].push_back(y);
}
int main()
{
freopen("climb.in","r",stdin);
freopen("climb.out","w",stdout);
n = read();
for(int i = 1; i <= n-1; i++)
{
u = read(); v = read();
add(u,v); add(v,u);
}
while(scanf("%d",&u) != EOF)
{
cnt++;
a[cnt] = u;
}
get_tree(1); dfs1(1,1);
last = 1;
for(int i = 1; i <= cnt; i++)
{
int Lca = lca(a[i],last);
if(flag == 1) break;
shuchu(++num,last,Lca);
shuchu(++num,a[i],Lca);
last = a[i];
}
if(flag == 1) printf("-1
");
else
{
printf("%d ",1);
for(int i = 1; i <= num; i++)
{
if(i & 1) for(int j = 1; j < path[i].size(); j++) printf("%d ",path[i][j]);
else for(int j = path[i].size()-2; j >= 0; j--) printf("%d ",path[i][j]);
}
shuchu(++num,a[cnt],1);
for(int j = 1; j < path[num].size(); j++) printf("%d ",path[num][j]);
}
printf("
");
fclose(stdin); fclose(stdout);
return 0;
}