7月26日2022多校冲刺NOIP联训测试6
A.Start
大模拟,不过硬是调了好几个小时还没有调出来......
对于普通牌来说,我们可以将其对 𝑝 的作用表示为一个数对(𝑎, 𝑏),即打出这张牌后 𝑝 = ⌊𝑝 ∗ 𝑎 + 𝑏 ⌋ ,不难发现,每种牌对应的数对如下.
牌型 | a | b | 牌型 | a | b |
---|---|---|---|---|---|
A1 | 1 | 1 | B1 | 1 | -1 |
A2 | 1 | 2 | B9 | 1 | -9 |
A5 | 1 | 5 | B19 | 1 | -19 |
A9 | 1 | 9 | C2 | 2 | 0 |
A19 | 1 | 19 | D2 | 0.5 | 0 |
A49 | 1 | 49 | E0 | 0 | 0 |
A99 | 1 | 99 | E49 | 0 | 49 |
E99 | 0 | 99 |
具体代码可以利用 𝑚𝑎𝑝 将字符串映射为点对.
对于解牌来说,因为种数很少,所以可以拿出来对每一种单独考虑.
PASS:较为简单,直接跳过即可.
TURN:使用一个变量 𝑑 来表示出牌顺序,令 𝑑 = −𝑑 .
DOUBLE:使用一个变量 𝑓 表示当前是否存在该状态.
部分实现:
mp["A1"]=(pair<ll,ll>){ 1,1 };
mp["A2"]=(pair<ll,ll>){ 1,2 };
mp["A5"]=(pair<ll,ll>){ 1,5 };
mp["A9"]=(pair<ll,ll>){ 1,9 };
mp["A19"]=(pair<ll,ll>){ 1,19 };
mp["A49"]=(pair<ll,ll>){ 1,49 };
mp["A99"]=(pair<ll,ll>){ 1,99 };
mp["B1"]=(pair<ll,ll>){ 1,-1 };
mp["B9"]=(pair<ll,ll>){ 1,-9 };
mp["B19"]=(pair<ll,ll>){ 1,-19 };
mp["C2"]=(pair<ll,ll>){ 2,0 };
mp["D2"]=(pair<ll,ll>){ 0.5,0 };
mp["E0"]=(pair<ll,ll>){ 0,0 };
mp["E49"]=(pair<ll,ll>){ 0,49 };
mp["E99"]=(pair<ll,ll>){ 0,99 };
if(w[3]<v) v=w[3],r=3;
if(w[1]<v) v=w[1],r=1;
if(w[0]<v) v=w[0],r=0;
if(w[2]<v) v=w[2],r=2;
if(w[4]<v) v=w[4],r=4;
inline bool judge()
{
if(used("PASS")) return 1;
if(used("TURN")) { d=-d; return 1; }
if(used("DOUBLE")) { fl=1;return 1; };
return 0;
}
B.Dream
观察题目中的性质, 𝑔 和 𝑧 的个数相等,且这个串被复制了一遍.
可以发现,这三个字符串中一定存在一个子串,使得其中有n个z和n个g,且最后一个位置不是串的末尾.
证明如下,不妨设 𝑔 的位置为,容易发现第 𝑛 个位置和第 2𝑛 个位置中间恰好有 𝑛 个 𝑧 .
因此,简单思考,我们只需先输出n个g(或n个z),再输出n个z(或n个g),最后再输出1个g(或z)即可.
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 2000001
#define rll rg ll
using namespace std;
inline ll read()
{
rll f=0,x=0;char ch=getchar();
while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
inline void write(ll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|48);
}
ll n;
char s[maxn];
int main()
{
n=read();
for(rll i=1;i<=n;i++) putchar('g');
for(rll i=1;i<=n;i++) putchar('z');
putchar('g');
return 0;
}
C.It
我们发现,如果只考虑上升的序列,这道题就很简单,就直接加,为什么下降会出现问题呢?因为下降不能直接减,下降如果直接减的话,可能会出现负数,而题意中是不允许有负数的,所以要用一下逆向思维.
怎么逆向呢?正着下降的话不就是从后往前上升吗?所以我们每次只考虑上升的,因为上升的就直接+1 就完了,于是这道题就正着跑一遍上升,倒着再跑一遍,如果这个数比前一个数大,就需要+1,小的话不管,等于也相等,最后要注意两种情况取最大值.
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 1000001
#define rll rg ll
using namespace std;
inline ll read()
{
rll f=0,x=0;char ch=getchar();
while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
inline void write(ll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|48);
}
ll n;
ll a[maxn];
ll ans[maxn];
ll b[maxn],cnt,c[maxn];
ll dsj[maxn],tot;
ll f1[maxn],f2[maxn];
int main()
{
n=read();
for(rll i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]==a[i-1]) b[cnt]++;
else c[++cnt]=a[i],b[cnt]=1;
}
if(c[1]<c[2]) f1[1]=2,dsj[++tot]=1;
else f1[1]=1;
if(c[cnt]>c[cnt-1]) f1[cnt]=1;
else f1[cnt]=2,dsj[++tot]=cnt;
for(rll i=2;i<cnt;i++)
{
if(c[i]>c[i-1]&&c[i]>c[i+1]) f1[i]=1;
else if(c[i]<c[i-1]&&c[i]<c[i+1]) f1[i]=2,dsj[++tot]=i;
}
for(rll i=1;i<=tot;i++)
{
rll id=dsj[i],w=1;
while(id&&f1[id]!=1) f2[id--]=w++;
f2[id]=max(f2[id],w);
id=dsj[i];w=1;
while(id<=cnt&&f1[id]!=1) f2[id++]=w++;
f2[id]=max(f2[id],w);
}
for(rll i=1;i<=cnt;i++)
for(rll j=1;j<=b[i];j++) write(f2[i]),putchar(' ');
return 0;
}
D.Possible
如果图是一棵树的话,那么答案其实是显然的.
任意图的两点间最短路貌似没有什么比Dijkstra更优的算法了,所以需要考虑这个图特有的性质,非树边是返祖边,树的深度不超过 20 ,相对来讲第二个条件的用处更为显然一些.
回忆树上最短路的求法,是由两条路径拼起来的,拼接的点为两个点的 lca,由于树的深度不超过 20,我们可以在该题中枚举两个点的拼接点是哪个,即路径上深度最小的点,注意它并不一定是 lca.
如 A 与 B 的拼接点为 C.
此时题目已经被转化成,如何求出 C 到 A 的最短路,即一个点到它子树内的某个点且不经过子树外的点的最短路,这样第一个性质似乎也变得可用起来,所有边都不是跨子树的边,所以可以依次递归每个子树进行求解.
具体的,我们按照 dfs 顺序遍历整棵树,到一个点时,将这个点子树内所有点和所有边加入到一张新图里,在新图中跑单源最短路,这样均摊时间复杂度是 20nlogn 可以通过.
接下来只要枚举这个拼接点求个最小值即可.
注意vis数组要用STL的bitset,否则会超时.
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 1000001
#define rll rg ll
using namespace std;
inline ll read()
{
rll f=0,x=0;char ch=getchar();
while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
inline void write(ll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);putchar(x%10|48);
}
struct node
{
ll x,dis;
inline friend bool operator<(rg node a,rg node b)
{
return a.dis>b.dis;
}
};
ll n,m,q;
vector<pair<ll,ll> > g[maxn],g1[maxn];
ll dep[maxn],fa[maxn][11],siz[maxn],son[maxn];
ll dfn[maxn],top[maxn],cnt;
vector<ll> dcl[maxn];
priority_queue<node> que;
map<ll,ll> mp[maxn];
bitset<maxn> fl;
ll dis[maxn];
inline void dij(rll x)
{
for(rll i=dcl[x].size()-1;i+1;i--) dis[dcl[x][i]]=0x7fffffffffffffff;
fl.reset();
dis[x]=0;que.push((node) { x,0 });
while(!que.empty())
{
rll t=que.top().x;que.pop();
if(fl[t]) continue;
fl[t]=1;
for(rll i=0;i<g1[t].size();i++)
{
rll to=g1[t][i].first;
if(dis[to]>dis[t]+g1[t][i].second)
{
dis[to]=dis[t]+g1[t][i].second;
que.push((node) { to,dis[to] });
}
}
}
for(rll i=dcl[x].size()-1;i+1;i--) mp[x][dcl[x][i]]=dis[dcl[x][i]];
}
inline void dfs(rll x,rll f)
{
dep[x]=dep[f]+1;
dcl[x].push_back(x);
for(rll i=0;i<g[x].size();i++)
{
rll to=g[x][i].first;
if(!dep[to])
{
fa[to][0]=x;
for(rll j=1;j<=5;j++) fa[to][j]=fa[fa[to][j-1]][j-1];
dfs(to,x);
for(rll j=0;j<dcl[to].size();j++) dcl[x].push_back(dcl[to][j]);
}
g1[x].push_back((pair<ll,ll>) { to,g[x][i].second });
g1[to].push_back((pair<ll,ll>) { x,g[x][i].second });
}
dij(x);
}
inline ll lca(rll x,rll y)
{
if(dep[x]>dep[y])swap(x,y);
for(int i=6;i+1;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
if(x==y)return x;
for(int i=6;i+1;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main()
{
n=read();m=read();q=read();
for(rll i=1,u,v,w;i<n;i++)
{
u=read();v=read();w=read();
g[u].push_back((pair<ll,ll>) { v,w });
g[v].push_back((pair<ll,ll>) { u,w });
}
for(rll i=n,u,v,w;i<=m;i++)
{
u=read();v=read();w=read();
g1[u].push_back((pair<ll,ll>) { v,w });
g1[v].push_back((pair<ll,ll>) { u,w });
}
dfs(1,0);
for(rll i=1,x,y;i<=q;i++)
{
x=read();y=read();
rll ans=0x7fffffffffffffff;
rll Lca=lca(x,y);
while(Lca)
{
ans=min(ans,mp[Lca][x]+mp[Lca][y]);
Lca=fa[Lca][0];
}
write(ans);puts("");
}
return 0;
}
--END--
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/p/16525492.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!