A. 玩游戏

考场做法用双指针向两侧更新,当左段点左移一位时,如果右端点不满足条件,则跳回肯定满足的位置。复杂度玄学

题解做法是类似最长子段和,如果有一个区间和为负,则维护的指针跳过去即可


B. 排列

考虑 dp

设 \(f[i][j][0/1][0/1]\) 表示长度为 \(i\) 的区间合并 \(j\) 次合并完,区间左边有没有值,右边有没有值的方案数

设这个区间的最大值位置在 \(k\),那么左边有 \(k-1\) 个值,右边 \(i-k\) 个值,考虑左右端点和合并次数结合组合意义转移即可

代码实现
#include<bits/stdc++.h>
using namespace std; const int maxn=1005;
int c[maxn][maxn];
int n,m;
long long f[maxn][maxn][2][2],mod;
int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-48;
ch=getchar();
}
return x*f;
}
void pre(){
c[0][0]=1;
for(int i=1;i<=n;i++){
c[i][0]=1;
for(int j=1;j<=i;j++){
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
// cout<<c[i][j]<<" ";
}
}
return ;
}
signed main(){
n=read();
m=read();
mod=read();
pre();
// cout<<c[5][2]<<endl;
for(int i=0;i<=m;i++)f[0][i][0][0]=f[0][i][1][1]=f[0][i][0][1]=f[0][i][1][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=1;k<=i;k++){
f[i][j][0][0]=(f[i][j][0][0]+f[k-1][j][0][1]*f[i-k][j][1][0]%mod*c[i-1][k-1]%mod)%mod;
f[i][j][0][1]=(f[i][j][0][1]+f[k-1][j][0][1]*f[i-k][j-1][1][1]%mod*c[i-1][k-1]%mod)%mod;
f[i][j][1][0]=(f[i][j][1][0]+f[k-1][j-1][1][1]*f[i-k][j][1][0]%mod*c[i-1][k-1]%mod)%mod;
f[i][j][1][1]=(f[i][j][1][1]+(f[k-1][j][1][1]*f[i-k][j][1][1]-(f[k-1][j][1][1]-f[k-1][j-1][1][1])*(f[i-k][j][1][1]-f[i-k][j-1][1][1]))%mod*c[i-1][k-1])%mod;
if(f[i][j][1][1]<mod)f[i][j][1][1]=f[i][j][1][1]%mod+mod;
// cout<<f[i][j][1][1]<<endl;
}
}
}
cout<<((f[n][m][0][0]-f[n][m-1][0][0])%mod+mod)%mod;
return 0;
}

C. 最短路

对于回去的路一定是走一段到1的路径,再往回走一段来时的路径

将回去的路起点和终点用 \(a\)、\(b\) 表示,\(f[i][j]\) 表示起点为 \(b\),终点为 \(a\),\(g[i][j]\) 表示起点终点均为 \(a\) 点距离

转移跑最短路实现

代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e6+5;
const int maxm=5e7+5;
const int maxk=1005;
const int inf=0x3f3f3f3f;
int n,m,val[maxk],dis1[maxk][maxk],dis[maxn],hd[maxn],cnt,x,y;
bool vis[maxn];
int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-48;
ch=getchar();
}
return x*f;
}
int id(int x,int y,int z){
return z*n*n+(x-1)*n+y;
}
struct Edge{
int nxt,to,val;
}edge[maxm];
void add(int u,int v,int w){
// cout<<u<<" "<<v<<" "<<w<<endl;
edge[++cnt].nxt=hd[u];
edge[cnt].to=v;
edge[cnt].val=w;
hd[u]=cnt;
return ;
}
void spfa(){
memset(dis,0x3f,sizeof dis);
dis[id(n,n,0)]=0;
queue<int>q;
q.push(id(n,n,0));
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=hd[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(dis[v]>dis[u]+edge[i].val){
dis[v]=dis[u]+edge[i].val;
if(!vis[v])vis[v]=true,q.push(v);
}
}
}
return ;
}
int main(){
n=read();
m=read();
for(int i=1;i<=n;i++)val[i]=read();
memset(dis1,0x3f,sizeof dis1);
for(int i=1;i<=m;i++){
x=read();
y=read();
dis1[x][y]=val[y];
}
for(int i=1;i<=n;i++)dis1[i][i]=0;
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis1[i][j]=min(dis1[i][j],dis1[i][k]+dis1[k][j]);
// cout<<dis1[2][4]<<endl;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
if(dis1[j][k]!=inf&&j!=k){
add(id(i,j,0),id(k,i,1),dis1[j][k]-val[k]);
}
if(dis1[i][k]!=inf&&dis1[k][j]!=inf){
add(id(i,j,1),id(i,k,0),dis1[i][k]+dis1[k][j]);
}
}
}
}
// cout<<"hhh"<<endl;
spfa();
if(dis[id(1,1,0)]==inf)puts("-1");
else cout<<dis[id(1,1,0)]+val[1];
return 0;
}

D. 矩形

考虑扫描线做法

当一个矩形的下边界加入时在线段树上区间覆盖

上边界去除标记

考虑如果是维护联通性,那么当一个位置有多个矩形覆盖,只需要和任意一个连边即可,所以线段树上每个点只存一种颜色,查询时递归到只有一种颜色的区间然后连边

修改时判断将要替换的颜色和当前颜色消失的时间大小,只保留时间靠后的颜色

代码略丑且长

代码实现
#include<bits/stdc++.h>
using namespace std;
int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-48;
ch=getchar();
}
return x*f;
}
const int maxn=2e5+5;
int n;
namespace p1{
int fa[maxn],ans;
struct Node{
int x,y,xx,yy;
}a[maxn],b,c;
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
x=find(x);
y=find(y);
if(x!=y)fa[x]=y;
return ;
}
void start(){
for(int i=1;i<=n;i++){
a[i].x=read();
a[i].y=read();
a[i].xx=read();
a[i].yy=read();
}
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
if(max(a[i].x,a[j].x)<=min(a[i].xx,a[j].xx)&&max(a[i].y,a[j].y)<=min(a[i].y,a[j].yy))merge(i,j);
continue;
b=a[i];
c=a[j];
if(b.x>c.x||b.x==c.x&&b.y>c.y)swap(b,c);
if(c.x<=b.xx){
if(c.y>=b.y&&c.y<=b.yy||c.yy>=b.y&&c.yy<=b.yy)merge(i,j);
}
}
}
for(int i=1;i<=n;i++){
if(fa[i]==i)ans++;
}
cout<<ans;
return ;
}
}
namespace p2{
int fa[maxn],x,y,xx,yy,ed[maxn],tot,ans;
struct Node{
int x,xx,y,op,id;
Node(){}
Node(int a,int b,int c,int d,int e):x(a),xx(b),y(c),op(d),id(e){}
}a[maxn]; bool cmp(Node a,Node b){
return a.y==b.y?a.op>b.op:a.y<b.y;
}
int find(int x){
return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
}
void merge(int x,int y){
x=find(x);
y=find(y);
if(x!=y)fa[x]=y;
return ;
}
struct Seg{
int l,r,type,num;
bool lazy,lazy1,flag;
}t[maxn*4];
void build(int p,int l,int r){
t[p].l=l;
t[p].r=r;
if(l==r)return ;
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
return ;
}
void update(int p){
if(t[p<<1].num>1||t[p<<1|1].num>1)t[p].num=2;
else if(t[p<<1].type==t[p<<1|1].type&&t[p<<1].num==1&&t[p<<1|1].num==1)t[p].num=1,t[p].type=t[p<<1].type;
else t[p].num=t[p<<1].num+t[p<<1|1].num,t[p].type=t[p<<1].type+t[p<<1|1].type;
if((!t[p<<1].num)||(!t[p<<1|1].num))t[p].flag=true;
else t[p].flag=false;
t[p].flag|=t[p<<1].flag|t[p<<1|1].flag;
return ;
}
void spread(int p){
t[p<<1].type=t[p<<1|1].type=t[p].type;
t[p<<1].lazy1=t[p<<1|1].lazy1=0;
t[p<<1].num=t[p<<1|1].num=t[p<<1].lazy=t[p<<1|1].lazy=1;
t[p].lazy=0;
return ;
}
void spread1(int p){
t[p<<1].num=t[p<<1|1].num=t[p<<1].type=t[p<<1|1].type=t[p<<1].lazy=t[p<<1|1].lazy=0;
t[p<<1].lazy1=t[p<<1|1].lazy1=1;
t[p].lazy1=0;
return ;
}
void ask(int p,int l,int r,int id){
if(t[p].num==0)return;
if(t[p].l>=l&&t[p].r<=r&&t[p].num==1){
// cout<<"hhh "<<id<<" "<<t[p].type<<endl;
// cout<<t[p].type<<endl;;
// cout<<id<<" "<<t[p].type<<endl;
merge(id,t[p].type);
return ;
}
if(t[p].lazy1)spread1(p);
if(t[p].lazy)spread(p);
int mid=t[p].l+t[p].r>>1;
if(l<=mid)ask(p<<1,l,r,id);
if(r>mid)ask(p<<1|1,l,r,id);
return ;
}
void change(int p,int l,int r,int id){
// cout<<"hhh "<<t[p].l<<" "<<t[p].r<<" "<<t[p].num<<" "<<t[p].flag<<" "<<id<<endl;
if(t[p].l>=l&&t[p].r<=r&&t[p].num<=1){//浼樺寲!!!
// cout<<t[p].type<<" "<<ed[t[p].type]<<endl;
if(ed[t[p].type]<ed[id]){
// cout<<"ppp "<<t[p].l<<" "<<t[p].r<<" "<<id<<endl;
t[p].type=id;
t[p].lazy=1;
t[p].num=1;
t[p].lazy1=0;
return ;
}
if(!t[p].flag)return ;
// if(t[p].l==t[p].r)return ;
}
if(t[p].lazy1)spread1(p);
if(t[p].lazy)spread(p);
int mid=t[p].l+t[p].r>>1;
if(l<=mid)change(p<<1,l,r,id);
if(r>mid)change(p<<1|1,l,r,id);
update(p);
return ;
}
void del(int p,int l,int r,int id){
// cout<<t[p].l<<" "<<t[p].r<<endl;
if(t[p].l>=l&&t[p].r<=r&&t[p].num<=1){ if(t[p].type==id){
t[p].type=t[p].num=t[p].lazy=0;
t[p].lazy1=1;
}
return ;
}
if(t[p].lazy1)spread1(p);
if(t[p].lazy)spread(p);
int mid=t[p].l+t[p].r>>1;
if(l<=mid)del(p<<1,l,r,id);
if(r>mid)del(p<<1|1,l,r,id);
update(p);
return ;
}
void start(){
int mx=0;
for(int i=1;i<=n;i++){
x=read();
y=read();
xx=read();
mx=max(mx,xx);
yy=read();
a[++tot]=Node(x,xx,y,1,i);
a[++tot]=Node(x,xx,yy,-1,i);
ed[i]=yy;
}
build(1,1,mx);
for(int i=1;i<=n;i++)fa[i]=i;
sort(a+1,a+tot+1,cmp); // cout<<endl;
for(int i=1;i<=tot;i++){
// cout<<a[i].y<<" "<<a[i].x<<" "<<a[i].xx<<" "<<a[i].id<<" "<<a[i].op<<" "<<ed[a[i].id]<<endl;
if(a[i].op==1){
ask(1,a[i].x,a[i].xx,a[i].id);
change(1,a[i].x,a[i].xx,a[i].id);
}
else{
del(1,a[i].x,a[i].xx,a[i].id);
}
}
for(int i=1;i<=n;i++){
if(fa[i]==i)ans++;
}
cout<<ans;
}
}
int main(){
// freopen("shuju.in","r",stdin);
// freopen("my.out","w",stdout);
n=read();
p2::start();
return 0;
}

noip模拟35的更多相关文章

  1. noip模拟35[第一次4题·裂了]

    noip模拟35 solutions 这是我第一次这么正式的考四个题,因为这四个题都出自同一个出题人,并不是拼盘拼出来的. 但是考得非常的不好,因为题非常难而且一直想睡觉.. 有好多我根本就不会的算法 ...

  2. Noip模拟35 2021.8.10

    考试题目变成四道了,貌似确实根本改不完... 不过给了两个小时颓废时间确实很爽(芜湖--) 但是前几天三道题改着不是很费劲的时候为什么不给放松时间, 非要在改不完题的时候颓?? 算了算了不碎碎念了.. ...

  3. NOIP模拟 35

    int乘爆见祖宗 难得地T3暴力打满 T1T2思路也都正确 然而T2没看出一个int乘爆直接滚粗.. 这谁抗的住啊... 跟天皇说我差点就rank1了 换来的只有一张奸笑的大脸和一堆垃圾的嘲讽 真巨啊 ...

  4. 2019.6.20 校内测试 NOIP模拟 Day 1 分析+题解

    这次是zay神仙给我们出的NOIP模拟题,不得不说好难啊QwQ,又倒数了~ T1 大美江湖 这个题是一个简单的模拟题.   ----zay 唯一的坑点就是打怪的时候计算向上取整时,如果用ceil函数一 ...

  5. NOIP模拟题17.9.26

    B 君的任务(task)[题目描述]与君初相识,犹如故人归.B 君看到了Z 君的第一题,觉得很难.于是自己出了一个简单题.你需要完成n 个任务,第i 任务有2 个属性ai; bi.其中ai 是完成这个 ...

  6. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  7. NOIP 模拟4 T2

    本题属于二和一问题 子问题相互对称 考虑对于问题一:知a求b 那么根据b数组定义式 显然能发现问题在于如何求dis(最短路) 有很多算法可供选择 dijsktra,floyed,bfs/dfs,spf ...

  8. 5.23考试总结(NOIP模拟2)

    5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...

  9. noip模拟22[d·e·f]

    noip模拟22 solutions 哈哈哈,这次暴力打满直接190,其实不到哈哈哈,187.. 这次的题暴力极其好打,但是正解确实不简单... 打了好久才改完这个题,改完的时候爽暴了 这些一个字母的 ...

随机推荐

  1. Maven项目思考&实战

    参考了网络上很多文章, 特此感谢. Maven项目规范 同一项目中所有模块版本保持一致 子模块统一继承父模块的版本 统一在顶层模块Pom的节中定义所有子模块的依赖版本号,子模块中添加依赖时不要添加版本 ...

  2. 【算法学习笔记】动态规划与数据结构的结合,在树上做DP

    前置芝士:Here 本文是基于 OI wiki 上的文章加以修改完成,感谢社区的转载支持和其他方面的支持 树形 DP,即在树上进行的 DP.由于树固有的递归性质,树形 DP 一般都是递归进行的. 基础 ...

  3. 使用Magicodes.IE快速导出Excel

    前言 总是有很多朋友咨询Magicodes.IE如何基于ASP.NET Core导出Excel,出于从框架的体验和易用性的角度,决定对Excel的导出进行独立封装,以便于大家更易于使用,开箱即用. 注 ...

  4. HCNA Routing&Switching之STP基础

    前文我们了解了VLAN动态注册协议GVRP相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15113770.html:今天我们来讨论下二层环路和STP相 ...

  5. LeetCode通关:哈希表六连,这个还真有点简单

    精品刷题路线参考: https://github.com/youngyangyang04/leetcode-master https://github.com/chefyuan/algorithm-b ...

  6. 算法竞赛中的常用JAVA API:PriorityQueue(优先队列)(转载)

    算法竞赛中的常用JAVA API:PriorityQueue(优先队列) PriorityQueue 翻译过来就是优先队列,本质是一个堆, 默认情况下堆顶每次都保留最小值,每插入一个元素,仍动态维护堆 ...

  7. MOOC大学计算机课程推荐

    转自:https://zhuanlan.zhihu.com/p/30659834  这个是大佬总结的, 大学计算机课程 以下课程是我在MOOC上找到的所有我认为讲的好的. 主要是中国大学MOOC,学堂 ...

  8. JVM-初见

    目录 JVM的体系结构 类加载器 双亲委派机制 Native PC程序计数器 方法区(Method Area) 栈 堆 调优工具 常见JVM调优参数 常见垃圾回收算法 引用计数算法 复制算法 标记-清 ...

  9. python3.9 manage.py runserver 报错问题解决

    报错信息如下 You have 13 unapplied migration(s). Your project may not work properly until you apply the mi ...

  10. SpringBoot 整合 SpringSecurity 梳理

    文档 Spring Security Reference SpringBoot+SpringSecurity+jwt整合及初体验 JSON Web Token 入门教程 - 阮一峰 JWT 官网 Sp ...