NOIP模拟98(多校30)
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)的更多相关文章
- NOIP模拟83(多校16)
前言 CSP之后第一次模拟赛,感觉考的一般. 不得不吐槽多校联测 OJ 上的评测机是真的慢... T1 树上的数 解题思路 感觉自己思维有些固化了,一看题目就感觉是线段树. 考完之后才想起来这玩意直接 ...
- NOIP模拟86(多校19)
T1 特殊字符串 解题思路 \(f_{i,j}\) 表示前 \(i\) 个字符中结尾为 \(j\) 的最大贡献. 转移枚举当前位置于之前位置结尾的组合加上贡献即可. 对于边界问题,容易发现选择 1 一 ...
- NOIP模拟92(多校25)
前言 所以说这次是 HZOI 多校联测巅峰????(题目,数据过水??) T1 石子合并 解题思路 签到题. 发现我们可以给每个数字附一个正负号,每个数字的贡献就是它本身乘上这个符号. 发现至少应该有 ...
- NOIP模拟84(多校17)
T1 宝藏 解题思路 考场上一眼出 \(nlog^2\) 做法,然后没看见是 1s 3e5 的数据,我竟然以为自己切了?? 考完之后尝试着把二分改为指针的移动,然后就过了??或许是数据水吧,感觉自己的 ...
- NOIP模拟85(多校18)
前言 好像每个题目背景所描述的人都是某部番里的角色,热切好像都挺惨的(情感上的惨). 然后我只知道 T1 的莓,确实挺惨... T1 莓良心 解题思路 首先答案只与 \(w\) 的和有关系,于是问题就 ...
- NOIP模拟88(多校21)
前言 对于这套题的总体感觉就是难,然后就是自己很菜... 对于 T1 考试时只会一个最垃圾的背包,考完之后对于思路这一块也不是很顺利,大概这就是薄弱的地方吧. 然后 T2 是比较简单的一道题了,但是考 ...
- NOIP模拟96(多校29)
T1 子集和 解题思路 大概是一个退背包的大白板,然而我考场上想复杂了,竟然还用到了组合数. 但是大概意思是一样的,有数的最小值一定是一个在 \(a\) 数组中存在的数字. 那么我们想办法除去它对应的 ...
- NOIP模拟99(多校31)
T1 法阵 解题思路 原题3100,张口放 T1(出题人原话) 思维题,合法的情况其实就是上下两个梯形拼起来的样子. 他们的边界都是在 \(i\) 轴上面,但是不能相交. 于是我们可以尝试两者相交的纵 ...
- noip模拟30[毛毛毛探探探]
\(noip模拟30\;solutions\) 所以说,这次被初中的大神给爆了????? 其实真的不甘心,这次考场上的遗憾太多,浪费的时间过多,心情非常不好 用这篇题解来结束这场让人伤心的考试吧 \( ...
- NOIP模拟 17.8.16
NOIP模拟17.8.16 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...
随机推荐
- react native 使用typescript
前言 TypeScript作为JavaScript的一个富类型扩展语言,深受代码风格严谨的前端开发者欢迎.但在react-native下,因为packager的配置困难,使用TypeScript一直是 ...
- Pytorch-tensor的感知机,链式法则
1.单层感知机 单层感知机的主要步骤: 1.对数据进行一个权重的累加求和,求得∑ 2.将∑经过一个激活函数Sigmoid,得出值O 3.再将O,经过一个损失函数mse_loss,得出值loss 4.根 ...
- marquee实现滚动
marquee的基本语法:<marquee> ... </marquee> 参数:1.滚动方向 (direction):left(左).right(右).up(上).down( ...
- 前端js解析识别图片二维码
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- pid算法函数实现,c语言版
#include <stdio.h> float pid(float setpoint, float process_variable, float kp, float ki, float ...
- docker containerd runc containerd-shim等组件的关系
早期 kubelet 创建容器工作原理 因为 docker 出生的比 k8s 早,所以 k8s 早期的容器运行时都是基于 docker 的,kubelet 通过 docker 的 api 创建容器.后 ...
- 团队管理|如何提高技术Leader的思考技巧?
简介: 技术Leader是一个对综合素质要求非常高的岗位,不仅要有解具体技术问题的架构能力,还要具备团队管理的能力,更需要引领方向带领团队/平台穿越迷茫进阶到下一个境界的能力.所以通常来说技术Lead ...
- 性能提升40%!阿里云神龙大数据加速引擎获TPCx-BB世界排名第一
简介:神龙大数据加速引擎,针对大数据常用组件,如Spark.Hadoop.Alluxio等,结合阿里云神龙架构的特性,进行软硬一体化优化,形成独一无二的性能优势,最终,使复杂SQL查询场景性能相比社 ...
- WPF 从零自己实现从 RealTimeStylus 获取触摸信息
本文将告诉大家什么是 RealTimeStylus 以及如何从零开始不使用 WPF 框架提供的功能从 RealTimeStylus 获取到触摸信息 开始之前先复习一下 Windows 的触摸演进.在上 ...
- vue-在公共icon封装组件里使用svg图标
1.安装svg-sprite-loader.package.json:"svg-sprite-loader": "^3.9.2", 2.build/webpac ...