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. IIS 出现405

    前言 在一次配置服务器中,出现一个问题,那就是使用put和delete 出现405. 当时我蒙了,调试的时候好好的,部署405. 原因是put和delete是非简单请求,也就是说非安全请求了. 这时候 ...

  2. 元素类型 “item” 相关联的 “name” 属性值不能包含 ‘<’ 字符

    Android构建时报错: app:lintVitalRelease[Fatal Error] :3:214: 与元素类型 "item" 相关联的 "name" ...

  3. ArcPy自动绘制大量地图并设置地图要素:Python

      本文介绍基于Python语言中ArcPy模块,实现ArcMap自动批量出图,并对地图要素进行自定义批量设置的方法. 1 任务需求   首先,我们来明确一下本文所需实现的需求.   现有通过Pyth ...

  4. 4.CSS层次选择器

    1.后代选择器:在某个元素的后面 1 /*后代选择器*/ 2 body p{ 3 background: crimson; 4 } 2.子选择器:仅一代 1 /*子选择器*/ 2 body>p{ ...

  5. 力扣448(java)-找到数组中所有消失的数(简单)

    题目: 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内.请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果. 示例 ...

  6. Flink 如何实时分析 Iceberg 数据湖的 CDC 数据

    简介: 数据湖的架构中,CDC 数据实时读写的方案和原理 本文由李劲松.胡争分享,社区志愿者杨伟海.李培殿整理.主要介绍在数据湖的架构中,CDC 数据实时读写的方案和原理.文章主要分为 4 个部分内容 ...

  7. 阿里云消息队列 RocketMQ 5.0 全新升级:消息、事件、流融合处理平台

    ​简介: RocketMQ5.0 的发布标志着阿里云消息从消息领域正式迈向了"消息.事件.流"场景大融合的新局面.未来阿里云消息产品的演进也将继续围绕消息.事件.流核心场景而开展. ...

  8. [FE] iframe 相关选项 x-frame-options: 设置 meta 标签无效 & helmet

    The X-Frame-Options HTTP 响应头是用来给浏览器 指示允许一个页面 可否在 <frame>, <iframe>, <embed> 或者 < ...

  9. mosquitto移植到ARM

      了解mosquitto的小伙伴多数都是想在arm中进行开发,所以将mosquitto移植到ARM板上就尤为重要了,当然也有在x86中进行应用开发的,想了解linux中安装mosquitto可以看我 ...

  10. go和c#实现斐波那契数列

    首先通过C#实现斐波那契数列: using System.Threading.Channels; namespace App001 { internal class Program { static ...