T1 构造字符串

解题思路

不算特别难的题,但是有一点细节。。。

首先需要并茶几缩一下点,然后判断一下是否合法,由于我们需要字典序最小的,因此我们应当保证一个联通块中标号较小的点为根节点。

那么对于所有不能够相等的标号对,我们再标号较大的点记下来标号较小的点的限制,然后从前往后扫一遍取 \(mex\) 值就好了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e3+10;
int n,m,fa[N],ans[N];
struct Node{int x,y,z;}s[N];
vector<int> v[N];
bitset<N> bit;
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
#undef int
int main()
{
#define int long long
freopen("str.in","r",stdin); freopen("str.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1,x,y,z;i<=m;i++)
{
x=read(); y=read(); z=read();
s[i]=(Node){x,y,z};
for(int j=1;j<=z;j++)
if(find(x+j-1)!=find(y+j-1))
if(find(y+j-1)>find(x+j-1)) fa[find(y+j-1)]=find(x+j-1);
else fa[find(x+j-1)]=find(y+j-1);
}
for(int i=1;i<=m;i++)
{
int p1=s[i].x+s[i].z,p2=s[i].y+s[i].z;
if(p1>n||p2>n) continue;
if(find(p1)==find(p2)) printf("-1"),exit(0);
if(find(p1)>find(p2)) swap(p1,p2);
v[find(p2)].push_back(find(p1));
}
for(int i=1,col;i<=n;i++)
{
if(find(i)!=i) continue; bit.reset();
for(auto it:v[i]) bit[ans[it]]=true;
col=0; while(bit[col]) col++; ans[i]=col;
}
for(int i=1;i<=n;i++) printf("%lld ",ans[find(i)]);
return 0;
}

T2 寻宝

解题思路

签到题。

首先把所有的可以互相到达的点用并茶几缩一下。

对于传送门的情况可以 Floyd 跑一遍也可以 bitset 整一遍,还可以对于一个询问直接搜一下。。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=5e4+10;
int n,m,t,q,col,vis[N],fa[N];
int tot=1,head[N],ver[N<<1],nxt[N<<1];
int d1[10]={0,1,-1,0,0};
int d2[10]={0,0,0,1,-1};
vector<int> v[N];
char ch[N];
int id(int x,int y){return (x-1)*m+y;}
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void add_edge(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void dfs(int x)
{
vis[x]=col;
for(int i=head[x];i;i=nxt[i])
if(vis[ver[i]]^col)
dfs(ver[i]);
}
#undef int
int main()
{
#define int long long
freopen("treasure.in","r",stdin); freopen("treasure.out","w",stdout);
n=read(); m=read(); t=read(); q=read();
for(int i=0;i<=m+1;i++) v[0].push_back('#'),v[n+1].push_back('#');
for(int i=1;i<=n;i++)
{
scanf("%s",ch+1); v[i].push_back('#');
for(int j=1;j<=m;j++) v[i].push_back(ch[j]);
v[i].push_back('#');
}
for(int i=1;i<=n*m;i++) fa[i]=i;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(v[i][j]!='#')
for(int k=1;k<=4;k++)
{
int x=i+d1[k],y=j+d2[k];
if(v[x][y]=='#') continue;
int p1=id(i,j),p2=id(x,y);
if(find(p1)!=find(p2)) fa[find(p1)]=find(p2);
}
for(int i=1,x,y,x2,y2;i<=t;i++)
{
x=read(); y=read(); x2=read(); y2=read();
if(find(id(x,y))==find(id(x2,y2))) continue;
add_edge(find(id(x,y)),find(id(x2,y2)));
}
while(q--)
{
int x,y,x2,y2,p1,p2;
x=read(); y=read(); x2=read(); y2=read();
p1=find(id(x,y)); p2=find(id(x2,y2)); col++; dfs(p1);
if(vis[p2]==col) printf("1\n"); else printf("0\n");
}
return 0;
}

T3 序列

解题思路

确实是一个李超线段树的好题。。。

发现一个位置 p 的最后答案其实就是对于以 p 为右端点向左边拓展,以 p+1 为左端点可以向右边拓展的最优解。

这两种情况类似只讨论第一种情况,记前缀和数组是 \(prea,preb\) 。

那么最优解就是 \(\max\limits_{1\le l\le r}\{(prea_r-prea_{l-1})-k(preb_r-preb_{l-1})\}\) 。

对于一个右端点 p 而言答案就是 \(prea_p-k\times preb_p+\max\limits_{0\le i<p}\{preb_i\times k-prea_i\}\) 。

直接以 k 为下标,李超线段树维护就好了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10,INF=1e18;
int n,m,cnt,lim1,lim2=INF,a[N],b[N],lsh[N],prea[N],preb[N],sufa[N],sufb[N],ans[N];
struct node{int p,k;}q[N];
vector< pair<int,int> > pre[N],suf[N];
inline int g(int pos,int k,int b){return lsh[pos]*k+b;}
struct Segment_Tree
{
struct Node{int k,b;}tre[N<<2];
void build(int x,int l,int r)
{
tre[x].b=-INF; tre[x].k=0; if(l==r) return ;
int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r);
}
void insert(int x,int l,int r,int k,int b)
{
if(g(l,k,b)>=g(l,tre[x].k,tre[x].b)&&g(r,k,b)>=g(r,tre[x].k,tre[x].b)) return tre[x]=(Node){k,b},void();
if(l==r) return ; int mid=(l+r)>>1;
if(g(mid,k,b)>g(mid,tre[x].k,tre[x].b)) swap(tre[x].k,k),swap(tre[x].b,b);
if(g(l,k,b)>g(l,tre[x].k,tre[x].b)) insert(ls,l,mid,k,b);
if(g(r,k,b)>g(r,tre[x].k,tre[x].b)) insert(rs,mid+1,r,k,b);
}
int query(int x,int l,int r,int pos)
{
if(l==r) return g(pos,tre[x].k,tre[x].b);
int mid=(l+r)>>1,temp=g(pos,tre[x].k,tre[x].b);
if(pos<=mid) return max(temp,query(ls,l,mid,pos));
return max(temp,query(rs,mid+1,r,pos));
}
}T1,T2;
#undef int
int main()
{
#define int long long
freopen("seq.in","r",stdin); freopen("seq.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=n;i++) a[i]=read(),b[i]=read(),prea[i]=prea[i-1]+a[i],preb[i]=preb[i-1]+b[i];
for(int i=n;i>=1;i--) sufa[i]=sufa[i+1]+a[i],sufb[i]=sufb[i+1]+b[i];
for(int i=1;i<=m;i++) q[i].p=read(),q[i].k=read(),lsh[i]=q[i].k,lim1=max(lim1,q[i].p),lim2=min(lim2,q[i].p+1);
sort(lsh+1,lsh+m+1); cnt=unique(lsh+1,lsh+m+1)-lsh-1; T1.build(1,1,cnt); T2.build(1,1,cnt);
for(int i=1;i<=m;i++)
{
pre[q[i].p].push_back({i,q[i].k});
if(q[i].p!=n) suf[q[i].p+1].push_back({i,q[i].k});
}
for(int i=0;i<=lim1;i++)
{
for(auto it:pre[i])
{
int temp=lower_bound(lsh+1,lsh+cnt+1,it.second)-lsh;
ans[it.first]+=prea[i]-it.second*preb[i]+T1.query(1,1,cnt,temp);
}
T1.insert(1,1,cnt,preb[i],-prea[i]);
}
for(int i=n+1;i>=lim2;i--)
{
T2.insert(1,1,cnt,sufb[i],-sufa[i]);
for(auto it:suf[i])
{
int temp=lower_bound(lsh+1,lsh+cnt+1,it.second)-lsh;
ans[it.first]+=sufa[i]-it.second*sufb[i]+T2.query(1,1,cnt,temp);
}
}
for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}

T4 构树

解题思路

只学会了一个状压的做法。。。

首先有一个定理:

Cayley定理:一个完全图有\(n^{n-2}\)棵无根生成树,经典问题prufer序列证明

扩展Cayley定理:被确定边分为大小为\(a_1,a_2,\cdots, a_m\)的连通块,则有\(n^{m-2}\prod {a_i}\)种生成树

然后我们枚举那些边是连接的然后根据上面的定理求出来一个至少有若干条边相同的值,然后二项式反演就好了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
#define count __builtin_popcount
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=8e3+10,mod=1e9+7;
int n,fac[N],ifac[N],g[N],f[N],fa[N],siz[N];
pair<int,int> s[N];
int power(int x,int y,int p=mod)
{
int temp=1; y=(y+mod-1)%(mod-1);
for(;y;y>>=1,x=x*x%p)
if(y&1) temp=temp*x%p;
return temp;
}
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void add(int &x,int y){x+=y;if(x>=mod)x-=mod;}
int C(int x,int y){if(x<y)return 0;return fac[x]*ifac[y]%mod*ifac[x-y]%mod;}
#undef int
int main()
{
#define int long long
freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
n=read(); fac[0]=ifac[0]=1;
for(int i=1,x,y;i<n;i++) s[i].first=read(),s[i].second=read();
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod; ifac[n]=power(fac[n],mod-2);
for(int i=n-1;i>=1;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
for(int sta=0;sta<(1ll<<n-1);sta++)
{
int temp=1;
for(int i=1;i<=n;i++) fa[i]=i,siz[i]=1;
for(int i=1;i<n;i++)
if(((sta>>i-1)&1)&&find(s[i].first)!=find(s[i].second))
{
siz[find(s[i].second)]+=siz[find(s[i].first)];
fa[find(s[i].first)]=find(s[i].second);
}
for(int i=1;i<=n;i++) if(find(i)==i) temp=temp*siz[i]%mod;
add(g[count(sta)],temp);
}
for(int i=0;i<n;i++) g[i]=g[i]*power(n,n-i-2)%mod;
for(int i=0;i<n;i++)
{
for(int j=i,bas=1;j<n;j++,bas=-bas)
add(f[i],(bas+mod)%mod*C(j,i)%mod*g[j]%mod);
}
for(int i=0;i<n;i++) printf("%lld ",f[i]);
return 0;
}

NOIP模拟98(多校30)的更多相关文章

  1. NOIP模拟83(多校16)

    前言 CSP之后第一次模拟赛,感觉考的一般. 不得不吐槽多校联测 OJ 上的评测机是真的慢... T1 树上的数 解题思路 感觉自己思维有些固化了,一看题目就感觉是线段树. 考完之后才想起来这玩意直接 ...

  2. NOIP模拟86(多校19)

    T1 特殊字符串 解题思路 \(f_{i,j}\) 表示前 \(i\) 个字符中结尾为 \(j\) 的最大贡献. 转移枚举当前位置于之前位置结尾的组合加上贡献即可. 对于边界问题,容易发现选择 1 一 ...

  3. NOIP模拟92(多校25)

    前言 所以说这次是 HZOI 多校联测巅峰????(题目,数据过水??) T1 石子合并 解题思路 签到题. 发现我们可以给每个数字附一个正负号,每个数字的贡献就是它本身乘上这个符号. 发现至少应该有 ...

  4. NOIP模拟84(多校17)

    T1 宝藏 解题思路 考场上一眼出 \(nlog^2\) 做法,然后没看见是 1s 3e5 的数据,我竟然以为自己切了?? 考完之后尝试着把二分改为指针的移动,然后就过了??或许是数据水吧,感觉自己的 ...

  5. NOIP模拟85(多校18)

    前言 好像每个题目背景所描述的人都是某部番里的角色,热切好像都挺惨的(情感上的惨). 然后我只知道 T1 的莓,确实挺惨... T1 莓良心 解题思路 首先答案只与 \(w\) 的和有关系,于是问题就 ...

  6. NOIP模拟88(多校21)

    前言 对于这套题的总体感觉就是难,然后就是自己很菜... 对于 T1 考试时只会一个最垃圾的背包,考完之后对于思路这一块也不是很顺利,大概这就是薄弱的地方吧. 然后 T2 是比较简单的一道题了,但是考 ...

  7. NOIP模拟96(多校29)

    T1 子集和 解题思路 大概是一个退背包的大白板,然而我考场上想复杂了,竟然还用到了组合数. 但是大概意思是一样的,有数的最小值一定是一个在 \(a\) 数组中存在的数字. 那么我们想办法除去它对应的 ...

  8. NOIP模拟99(多校31)

    T1 法阵 解题思路 原题3100,张口放 T1(出题人原话) 思维题,合法的情况其实就是上下两个梯形拼起来的样子. 他们的边界都是在 \(i\) 轴上面,但是不能相交. 于是我们可以尝试两者相交的纵 ...

  9. noip模拟30[毛毛毛探探探]

    \(noip模拟30\;solutions\) 所以说,这次被初中的大神给爆了????? 其实真的不甘心,这次考场上的遗憾太多,浪费的时间过多,心情非常不好 用这篇题解来结束这场让人伤心的考试吧 \( ...

  10. NOIP模拟 17.8.16

    NOIP模拟17.8.16 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

随机推荐

  1. 常见的PLC通信协议及相关介绍

    2023-07-26 一.常见的PLC通信协议: Modbus:Modbus是一种串行通信协议,它支持多种物理层接口(如RS-232.RS-485等),可以实现PLC与其他设备(如HMI.变频器等)之 ...

  2. React的理解以及特性

    一.是什么 React,用于构建用户界面的 JavaScript 库,提供了 UI 层面的解决方案 遵循组件设计模式.声明式编程范式和函数式编程概念,以使前端应用程序更高效 使用虚拟DOM来有效地操作 ...

  3. Springmvc来做甘特图的显示控制。

    springmvc没有Springboot好用:所以就用了ajax通信来获取数据,这其中有不少坑,我来带大家踩一踩. 1.在控制层中,接口不能直接返回Json格式. 我的解决方法可以使通过map,或者 ...

  4. 基于 Serverless 打造如 Windows 体验的个人专属家庭网盘

    ​简介:虽然现在市面上有些网盘产品, 如果免费试用,或多或少都存在一些问题, 可以参考文章<2020 国内还能用的网盘推荐>.本文旨在使用较低成本打造一个 "个人专享的.无任何限 ...

  5. Nacos2.0的K8s服务发现生态应用及规划

    ​简介:Nacos 是阿里巴巴于 2018 年开源的注册中心及配置中心产品,帮助用户的分布式微服务应用进行服务发现和配置管理功能.随着 Nacos2.0 版本的发布,在性能和扩展性上取得较大突破后,社 ...

  6. 如何玩转 WebGL 并行计算

    ​简介: 如今在 Web 端使用 WebGL 进行高性能计算已有不少实践,例如在端智能领域中的 tensorflow.js,再比如可视化领域中的 Stardust.js. ​ 作者 | 沧东 来源 | ...

  7. dotnet 读 WPF 源代码笔记 简单聊聊文本布局换行逻辑

    在 WPF 里面,带了基础的文本库功能,如 TextBlock 等.文本库排版的重点是在文本的分行逻辑,也就是换行逻辑,如何计算当前的文本字符串到达哪个字符就需要换到下一行的逻辑就是文本布局的重点模块 ...

  8. Gradle8.4构建SpringBoot多模块项目

    Gradle8.4构建SpringBoot多模块项目 一.基本 1.版本 这个版本是Jdk8最后一个SpringBoot版本 软件 版本 Gradle 8.4 SpringBoot 2.7.15 JD ...

  9. 03. go-zero简介及如何学go-zero

    目录 一.go-zero简介及如何学go-zero 1.go-zero官方文档 2.go-zero微服务框架入门教程 3.go-zero最佳实践 4.学习资料 二.go-zero环境搭建 1.GO环境 ...

  10. docker-compose 配置LNMP环境

    仓库地址: https://gitee.com/haima1004/docker-lnmp 参考文档: 视频地址: https://www.bilibili.com/video/BV1S54y1B7K ...