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. redis 简单整理——复制的原理[二十三]

    前言 简单介绍一下复制的原理. 正文 在从节点执行slaveof命令后,复制过程便开始运作,下面详细介绍建立 复制的完整流程. 1)保存主节点(master)信息. 执行slaveof后从节点只保存主 ...

  2. stm32串口晶振不对输出乱码+汇承HC-14lora模块

    最近要用到一个lora无线透传模块,然后就先用两个32开发板(用的STM32F103C8T6)试试简单的收发数据.结果,第一步串口发送一句话就寄了,我串口打印了"hi",结果出现了 ...

  3. Borůvka MST算法

    当我认为最MST(最小生成树)已经没有什么学的了,才发现世界上还有个这个kruskal和prim结合的玩意 Borůvka 运用并查集的思想,先将每一个初始点集初始化为有且只有自己的点集,然后每一次合 ...

  4. 【pytorch学习】之微积分

    4 微积分 在2500年前,古希腊人把一个多边形分成三角形,并把它们的面积相加,才找到计算多边形面积的方法.为了求出曲线形状(比如圆)的面积,古希腊人在这样的形状上刻内接多边形.如图所示,内接多边形的 ...

  5. 一遇到复杂分析查询就卡顿?MySQL分析实例了解一下

    随着企业数据爆发式增长,MySQL分析查询卡顿问题越来越多,用户时效性不能保证,精细化运营诉求不能满足.如何能无缝对接业务库,实现毫秒级针对万亿级数据进行即时的多维分析透视和业务探索,MySQL分析实 ...

  6. 首次公开!阿里云开源PolarDB总体架构和企业级特性

    ​简介:在3月2日的阿里云开源 PolarDB 企业级架构发布会上,阿里云 PolarDB 内核技术专家北侠带来了主题为<PolarDB 总体架构设计和企业级特性>的精彩演讲. 在3月2日 ...

  7. CPU Burst有副作用吗?让数学来回答!| 龙蜥技术

    ​简介: 使用CPU Burst的副作用是什么?是否有不适用的场景呢?戳我给你答案~ 编者按:CPU Burst 特性已合入 Linux 5.14,Anolis OS 8.2.Alibaba Clou ...

  8. Python多线程编程深度探索:从入门到实战

    title: Python多线程编程深度探索:从入门到实战 date: 2024/4/28 18:57:17 updated: 2024/4/28 18:57:17 categories: 后端开发 ...

  9. VSCode+VUE+ESLint以达到保存自动格式化

    首先打开VSCode在.eslintrc.js中加入以下代码(不知道怎么找可以ctrl+shift+p进行搜索),添加 vscode 终端启动服务 // 添加⾃定义规则 'prettier/prett ...

  10. C#的基于.net framework的Winform编程 - 编程手把手系列文章

    对于C#,笔者最早接触的是ASP.NET里的开发,后面对Winform程序也有一定的开发,但是真正理解和重新编码是这些年的事,在我的C#标签里有一些例子,记录了winform程序开发的一些功能.此文只 ...