T1:
题意:给定1到n的排列,依次入栈,想什么时候pop什么时候pop,求字典序最大的出栈顺序
思路:显然是个贪心,每次比较当前栈顶和后缀max,栈顶大就pop,后缀max大就push。最后pop到空
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 1000005
using namespace std; int n;
int a[MAXN],mx[MAXN];
int stk[MAXN],top=0;
char tmp[20];
inline int read(){
scanf("%s",tmp);
int rtn=0;
for(register char *s=tmp;*s;++s) rtn=rtn*10+*s-'0';
return rtn;
}
inline void write(int x){
memset(tmp,0,sizeof tmp);
int cnt=0;
while(x){
tmp[cnt++]=x%10+'0';
x/=10;
}
for(register int i=cnt-1;~i;--i) putchar(tmp[i]);
putchar(' ');
}
int main(){
freopen("sort.in","r",stdin);
freopen("sort.out","w",stdout);
n=read();
for(register int i=1;i<=n;++i) a[i]=read();
for(register int i=n;i;--i) mx[i]=max(mx[i+1],a[i]);
for(register int i=1;i<=n;++i){
stk[++top]=a[i];
while(stk[top]>mx[i+1]) write(stk[top--]);
}
while(top) write(stk[top--]);
return 0;
}
T2:
题面:一棵树,每次删除某条边,求当前森林中所有树的直径之积
思路:
显然删边没有加边好写,于是倒着做。对于两棵树,在合并的时候,新树的直径肯定是原树中的某条路径,于是先nlogn地处理出来(随便倍增啊链剖啊啥的)。
合并的新直径,有两种情况,一种是合并前的某棵树的直径,另一种是新产生的一条路径。
可以yy出一个性质,合并时产生的直径的端点一定是原来直径的端点。
于是求一下路径长度取个max就好
代码:
#include<bits/stdc++.h>
#define MAXN 100005
#define MOD 1000000007
using namespace std; int n;
int ans=1;
//=========================================================
char read_s[30];
int read(){
scanf("%s",read_s);
int f=1;
int rtn=0;
for(char *s=read_s;*s;++s)
if(*s==-1) f=-1;
else rtn=rtn*10+*s-'0';
return rtn*f;
}
//=========================================================
#define inv(x) pow_(x,MOD-2)
int pow_(int d,int c){
int rtn=1;
for(;c;c>>=1,d=1ll*d*d%MOD)
if(c&1)
rtn=1ll*rtn*d%MOD;
return rtn;
}
//=========================================================
struct t1{
int frm,to,nxt;
}edge[MAXN<<1]; int cnt_edge=0;
int fst[MAXN];
void addedge(int x,int y){
edge[++cnt_edge].to=y;
edge[cnt_edge].frm=x;
edge[cnt_edge].nxt=fst[x];
fst[x]=cnt_edge;
}
int val[MAXN];
int fth[MAXN],top[MAXN],siz[MAXN],son[MAXN];
int dis[MAXN],dpt[MAXN];
void dfs1(int now){
siz[now]=1;
for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
int aim=edge[tmp].to;
if(aim==fth[now]) continue;
fth[aim]=now;
dpt[aim]=dpt[now]+1;
dis[aim]=dis[now]+val[aim];
dfs1(aim);
siz[now]+=siz[aim];
if(siz[aim]>siz[son[now]]) son[now]=aim;
}
}
void dfs2(int now,int tp){
top[now]=tp;
if(son[now]) dfs2(son[now],tp);
for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
int aim=edge[tmp].to;
if(aim==son[now]||aim==fth[now]) continue;
dfs2(aim,aim);
}
}
int _lca(int a,int b){
while(top[a]^top[b]){
if(dpt[fth[top[a]]]<dpt[fth[top[b]]]) swap(a,b);
a=fth[top[a]];
}
return dpt[a]<dpt[b]? a:b;
}
int get_dis(int a,int b){
int lca=_lca(a,b);
return dis[a]+dis[b]-dis[lca]-dis[fth[lca]];
}
//===============================================================
int del[MAXN];
int father[MAXN];
int findfather(int x){return father[x]==x?x:father[x]=findfather(father[x]);}
int end[MAXN][2],length[MAXN];
int end_tmp[2];
int print[MAXN];
int read_x,read_y;
int main(){
// freopen("forest.in","r",stdin);
// freopen("forest.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",val+i);
for(int i=1;i<n;++i){
scanf("%d%d",&read_x,&read_y);
addedge(read_x,read_y);
addedge(read_y,read_x);
}
dis[1]=val[1];
dpt[1]=1;
dfs1(1);
dfs2(1,1);
for(int i=1;i<n;++i) scanf("%d",del+i);
for(int i=1;i<=n;++i) end[i][0]=end[i][1]=father[i]=i,ans=1ll*ans*val[i]%MOD;
for(int i=1;i<=n;++i) length[i]=val[i];
print[n] = ans;
for(int i=n-1;i;--i){
int u=edge[del[i]<<1].frm,v=edge[del[i]<<1].to;
u = findfather( u ) , v = findfather( v );
int ll;
if(length[v] > length[u])
end_tmp[0]=end[v][0] , end_tmp[1]=end[v][1] , ll=length[v];
else
end_tmp[0]=end[u][0] , end_tmp[1]=end[u][1] , ll=length[u];
ans = 1ll * ans * inv(length[v]) % MOD;
ans = 1ll * ans * inv(length[u]) % MOD;
for(int j=0;j<2;++j){
for(int k=0;k<2;++k){
int dd=get_dis(end[u][j],end[v][k]);
if(dd > ll)
end_tmp[0]=end[u][j] , end_tmp[1]=end[v][k] , ll=dd;
}
}
if(i&1) father[v]=u,length[u]=ll,end[u][0]=end_tmp[0],end[u][1]=end_tmp[1];
else father[u]=v,length[v]=ll,end[v][0]=end_tmp[0],end[v][1]=end_tmp[1];
ans = 1ll * ans * ll % MOD;
print[i] = ans;
}
for(int i=1;i<=n;++i) printf("%d\n",print[i]);
return 0;
}
T3:
题面:仙人掌上最短路
思路:GG,缩环什么的,自己yy就好,tarjan啊………………反正我是背不住版