T1 交通

解题思路

把环视为点,对于原图中每一个点的两条入边以及两条出边分别连边。

优于保证了原图中每个点出入度都是 2 因此新图中一定由若干个偶数环所组成的。

并且对于环中一定是只能间隔着选点,因此每个环有 2 种选择,答案就是 \(2^{环数}\)

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
int n,ans,in[N][2],out[N][2],t1[N],t2[N],fa[N<<1];
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
int power(int x,int y)
{
int temp=1;
while(y)
{
if(y&1) temp=temp*x%mod;
x=x*x%mod; y>>=1;
}
return temp;
}
signed main()
{
freopen("a.in","r",stdin); freopen("a.out","w",stdout);
n=read();
for(int i=1,x,y;i<=2*n;i++)
{
fa[i]=i; x=read(); y=read();
in[y][t1[y]++]=i; out[x][t2[x]++]=i;
}
for(int i=1;i<=n;i++)
{
if(find(in[i][0])!=find(in[i][1])) fa[find(in[i][0])]=find(in[i][1]);
if(find(out[i][0])!=find(out[i][1])) fa[find(out[i][0])]=find(out[i][1]);
}
for(int i=1;i<=2*n;i++) ans+=(find(i)==i);
printf("%lld",power(2,ans)%mod);
return 0;
}

T2 小P的单调数列

解题思路

\(n^3\) 的 DP 比较好想, \(f_{i,j}\) 表示默认选择第 \(i\) 个并且当前段数为 \(j\) 个的情况直接暴力枚举当前个,前一个,以及对应段数就好了。

可以发现只选择一个最长上升子序列和一个最长下降子序列其实是最优的方案,因为如果再加入一段序列答案会变优的情况只能是新加入序列比上升段或者下降段的总和更大的时候。。

这种情况显然是不存在的,时间复杂度降到 \(n^2\) 在加上棵线段树就可以达到 \(nlogn\) 的复杂度了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<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=1e5+10,INF=1e18;
int n,cnt,lsh[N],s[N];
double ans;
struct Segment_Tree
{
int tre[N<<2];
void push_up(int x){tre[x]=max(tre[ls],tre[rs]);}
void insert(int x,int l,int r,int pos,int val)
{
if(l==r) return tre[x]=max(tre[x],val),void();
int mid=(l+r)>>1;
if(pos<=mid) insert(ls,l,mid,pos,val);
else insert(rs,mid+1,r,pos,val);
push_up(x);
}
int query(int x,int l,int r,int L,int R)
{
if(L>R) return -INF;
if(L<=l&&r<=R) return tre[x];
int mid=(l+r)>>1,maxn=-INF;
if(L<=mid) maxn=max(maxn,query(ls,l,mid,L,R));
if(R>mid) maxn=max(maxn,query(rs,mid+1,r,L,R));
return maxn;
}
}T[3];
signed main()
{
freopen("b.in","r",stdin); freopen("b.out","w",stdout);
n=read(); for(int i=1;i<=n;i++) lsh[i]=s[i]=read();
sort(lsh+1,lsh+n+1); cnt=unique(lsh+1,lsh+n+1)-lsh-1;
for(int i=1;i<=n;i++) s[i]=lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh;
for(int i=1;i<=n;i++)
for(int k=2;k>=1;k--)
{
if(k==1) T[1].insert(1,1,cnt,s[i],lsh[s[i]]),ans=max(ans,(1.0*lsh[s[i]])/(1.0*k));
int temp=T[k-1].query(1,1,cnt,s[i],s[i]);
if(k&1) temp=max(temp,max(T[k].query(1,1,cnt,1,s[i]-1),T[k-1].query(1,1,cnt,s[i]+1,cnt)));
else temp=max(temp,max(T[k-1].query(1,1,cnt,1,s[i]-1),T[k].query(1,1,cnt,s[i]+1,cnt)));
T[k].insert(1,1,cnt,s[i],temp+lsh[s[i]]);
ans=max(ans,1.0*(1.0*temp+1.0*lsh[s[i]])/(1.0*k));
}
printf("%.3lf",ans);
return 0;
}

T3 矩阵

解题思路

其实我们只要考虑如何消掉前两行和前两列就好了(证明就。。)

假设矩阵数组是 \(s\) 那么先把 \(s_{1,1}\) 和 \(s_{2,2}\) 搞成相同的,接下来对于前两行,我们肯定是先把他们每一列都消成一样的最后再统一干掉。

那么我们已经确定了 \(s_{2,2}\) 就可以对应确定 \(s_{1,2}\) 相应的 \(s_{2,3}\) 也被确定了,以此类推,最后一个可以直接更改。

对于两列的情况也是相同的方法

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<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,cnt,s[N][N];
struct Node{int opt,x,dat;}q[N*6];
void check(){cout<<"Check: "<<cnt<<endl;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++)cout<<s[i][j]<<' ';cout<<endl;}}
signed main()
{
freopen("c.in","r",stdin); freopen("c.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j]=read();
if(n==1){cout<<m<<endl;for(int i=1;i<=m;i++)printf("2 %lld %lld\n",i,-s[1][i]);exit(0);}
if(m==1){cout<<n<<endl;for(int i=1;i<=n;i++)printf("1 %lld %lld\n",i,-s[i][1]);exit(0);}
if(s[1][1]!=s[2][2])
{
int temp=s[2][2]-s[1][1];
q[++cnt]=(Node){1,1,temp};
for(int i=1;i<=m;i++) s[1][i]+=temp;
}
for(int i=2;i<m;i++)
if(s[1][i]!=s[2][i])
{
int temp=s[2][i]-s[1][i];
q[++cnt]=(Node){3,i-1,temp};
for(int x=1,y=i;x<=n&&y<=m;x++,y++)
s[x][y]+=temp;
}
if(s[1][m]!=s[2][m])
{
q[++cnt]=(Node){3,m-1,s[2][m]-s[1][m]};
s[1][m]=s[2][m];
}
for(int i=2;i<n;i++)
if(s[i][1]!=s[i][2])
{
int temp=s[i][2]-s[i][1];
q[++cnt]=(Node){3,1-i,temp};
for(int x=i,y=1;x<=n&&y<=m;x++,y++)
s[x][y]+=temp;
}
if(s[n][1]!=s[n][2])
{
q[++cnt]=(Node){3,1-n,s[n][2]-s[n][1]};
s[n][1]=s[n][2];
}
for(int i=1;i<=m;i++)
if(s[1][i])
{
q[++cnt]=(Node){2,i,-s[1][i]};
for(int j=n;j>=1;j--)
s[j][i]-=s[1][i];
}
for(int i=1;i<=n;i++)
if(s[i][1])
{
q[++cnt]=(Node){1,i,-s[i][1]};
for(int j=m;j>=1;j--)
s[i][j]-=s[i][1];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j])
printf("-1"),exit(0);
printf("%lld\n",cnt);
for(int i=1;i<=cnt;i++) printf("%lld %lld %lld\n",q[i].opt,q[i].x,q[i].dat);
return 0;
}

T4 花瓶

解题思路

斜率优化 DP

\(f_{i,j}\) 表示当前到 \(i\) 之前的端的右端点是 \(j\) 的最优解, \(s_i\) 表示前缀和

\[f_{i,j}=\max\limits_{0\le k<j}\{f_{j,k}+(s_i-s_j)(s_j-s_k)\}
\]
\[f_{i,j}=(s_i-s_j)s_j+\max\limits_{0\le k<j}\{f_{j,k}-(s_i-s_j)s_k\}
\]

对于 \(s_a<s_b\) 并且 \(b\) 优于 \(a\) 就有:

\[\dfrac{f_{j,a}-f_{j,b}}{s_a-s_b}>(s_i-s_j)
\]

因此我们可以枚举原序列的 \(j\) 并且对于按照 \(s\) 排完序后按照 \(s\) 从大到小进行枚举 \(i\) 。

并且对于每一次的标号小于 \(j\) 的维护出一个上凸包,枚举 \(i\) 的时候更新答案就好了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<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=5e3+10;
int INF,n,ans,q[N],a[N],f[N][N],pre[N];
struct Node
{
int id,dat;
bool friend operator < (Node x,Node y)
{
if(x.dat==y.dat) return x.id<y.id;
return x.dat<y.dat;
}
}s[N];
signed main()
{
freopen("d.in","r",stdin); freopen("d.out","w",stdout);
n=read(); memset(f,0x8f,sizeof(f)); INF=f[0][0];
for(int i=1;i<=n;i++) a[i]=read(),pre[i]=s[i].dat=s[i-1].dat+a[i],f[i][0]=f[i][i]=0,s[i].id=i;
sort(s+0,s+n+1);
for(int j=1;j<=n;j++)
{
int head=1,tail=0;
for(int i=0;i<=n;i++)
{
if(s[i].id>=j) continue;
while(head<tail&&(f[j][s[i].id]-f[j][s[q[tail]].id])*(s[q[tail]].dat-s[q[tail-1]].dat) >= (f[j][s[q[tail]].id]-f[j][s[q[tail-1]].id])*(s[i].dat-s[q[tail]].dat) )tail--;
q[++tail]=i;
}
for(int i=n;i>=0;i--)
{
if(s[i].id<=j) continue;
while(head<tail&&(f[j][s[q[head]].id]-f[j][s[q[head+1]].id])<(s[i].dat-pre[j])*(s[q[head]].dat-s[q[head+1]].dat)) head++;
f[s[i].id][j]=max(f[s[i].id][j],(s[i].dat-pre[j])*pre[j]+f[j][s[q[head]].id]-(s[i].dat-pre[j])*s[q[head]].dat);
}
}
for(int i=0;i<=n;i++) ans=max(ans,f[n][i]); printf("%lld",ans);
return 0;
}

NOIP模拟61的更多相关文章

  1. Noip模拟61 2021.9.25

    T1 交通 考场上想了一个$NPC$.应该吧,是要求出图里面的所有可行的不重复欧拉路 无数种做法都无法解出,时间也都耗在这个上面的,于是就考的挺惨的 以后要是觉得当前思路不可做,就试着换一换思路,千万 ...

  2. 2021.9.25考试总结[NOIP模拟61]

    终于有点阳间题了然而挂了60pts 哈哈 T1 交通 类似简单题,限制看似很复杂,但不难发现当确定一条边是否被删后会产生裙带关系,很多边会跟着自动被确定是否被删. 仔细观察可以得出这种关系会构成偶环结 ...

  3. NOIP模拟17.9.22

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

  4. NOIP 模拟4 T2

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

  5. noip模拟32[好数学啊]

    noip模拟32 solutions 真是无语子,又没上100,无奈死了 虽然我每次都觉得题很难,但是还是有好多上100的 战神都200多了,好生气啊啊啊 从题开始变难之后,我的时间分配越来越不均匀, ...

  6. 2021.9.17考试总结[NOIP模拟55]

    有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...

  7. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  8. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  9. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  10. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

随机推荐

  1. asp .net core 单页应用

    前言 单页应用其实就是 asp.net core 来作为js service,个人觉得这样更好调试,这种比较适合中小型业务. 正文 因为自己写过混合app是ionic,那么就尝试一下angular的单 ...

  2. c# webapi swagger

    如何配置swagger? 在使用项目中,我们希望去查看我们的webapi的测试,那么我们是需要去有一个集成的测试的. 步骤 1.在nutget管理包中下载swagger包. 2.这样会在App_sta ...

  3. Pytorch-tensor的分割,属性统计

    1.矩阵的分割 方法:split(分割长度,所分割的维度),split([分割所占的百分比],所分割的维度) a=torch.rand(32,8) aa,bb=a.split(16,dim=0) pr ...

  4. tomcat 服务版本内存设置

    1. 安装服务,如需指定java路径,需要在service.bat 中修改, 如下图 其中 pa代表当前目录 2. 安装服务, service.bat install 服务名,如下图示例 3. 内存设 ...

  5. Vue3 解构赋值失去响应式引发的思考

    前言 vue3发布以来经历两年风头正盛,现在大有和react 平分秋色的势头,我们知道他是基于proxy 实现响应式的能力, 解决了vue2所遗留下来的一些问题,同时也正由于proxy的特性,也提高了 ...

  6. git默认忽略文件名称大小写

    0. 现象 当将文件名称test 修改为 Test时,git提交记录检测不到变化 1.原因 Git默认设置忽略文件名大小写是因为不同操作系统对文件名大小写的处理方式不同,为了避免在不同操作系统之间出现 ...

  7. Service Mesh 从“趋势”走向“无聊”

    简介: 过去一年,阿里巴巴在 Service Mesh 的探索道路上依旧扎实前行,这种坚定并非只因坚信 Service Mesh 未来一定是云计算基础技术的关键组成部分,还因需要借这一技术趋势去偿还过 ...

  8. [Trading] 买卖如何移动 ( 影响 ) 市场价格

    大多数人都知道市场价格的变化是因为买卖行为,但却没有多少人了解买卖行为是如何影响市场价格的. 乍一看,这可能令人困惑,因为每一笔市场交易都要求总有一个买家和一个卖家. 首先,重要的是要明白市场上总是有 ...

  9. [Gin] 传统 for 循环中的语义通用化,在 golang 中使用分号 ; 替代 && 流程控制

    // gin.go // HandlerFunc defines the handler used by gin middleware as return value. type HandlerFun ...

  10. 1.权限控制RBAC

    官方参考地址:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/#privilege-escalation-prev ...