T1

考场乱搞出锅了...

正解:

把原序列按k往左和往右看成两个序列,求个前缀和,找下一个更新的位置,直接暴跳。

Code
#include<cstdio>
#include<cstring>
#define MAX 100100
#define re register
#define int long long
namespace OMA
{
int t,n,k;
int c[MAX],a[MAX],b[MAX];
int sum[MAX][2],next[MAX][2];
struct stream
{
template<typename type>inline stream &operator >>(type &s)
{
int w=1; s=0; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*=w,*this;
}
}cin;
signed main()
{
cin >> t;
while(t--)
{
memset(next,0,sizeof(next));
cin >> n >> k;
for(re int i=1; i<=n; i++)
{ cin >> c[i]; }
int len1 = 1,len2 = 1;
a[1] = b[1] = 0;
for(re int i=k; i>=2; i--)
{ a[++len1] = c[i]; }
for(re int i=k+1; i<=n; i++)
{ b[++len2] = c[i]; }
for(re int i=1; i<=len1; i++)
{ sum[i][0] = sum[i-1][0]+a[i]; }
for(re int i=1; i<=len2; i++)
{ sum[i][1] = sum[i-1][1]+b[i]; }
int nim = sum[1][0],pos = 1;
for(re int i=2; i<=len1; i++)
{ if(sum[i][0]<nim){ nim = sum[i][0],next[pos][0] = i,pos = i; } }
nim = sum[len1][0],pos = len1;
for(re int i=len1-1; i>=1; i--)
{ if(sum[i][0]<nim){ nim = sum[i][0],next[pos][0] = i,pos = i; } }
nim = sum[1][1],pos = 1;
for(re int i=2; i<=len2; i++)
{ if(sum[i][1]<nim){ nim = sum[i][1],next[pos][1] = i,pos = i; } }
nim = sum[len2][1],pos = len2;
for(re int i=len2-1; i>=1; i--)
{ if(sum[i][1]<nim){ nim = sum[i][1],next[pos][1] = i,pos = i; } }
if(sum[len1][0]+sum[len2][1]>0)
{ printf("No\n"); continue ; }
int l = 1,r = 1;
bool flag = true;
while(next[l][0]||next[r][1])
{
flag = !next[l][0]?false:true;
for(re int i=l+1; i<=next[l][0]; i++)
{
if(sum[i][0]+sum[r][1]>0)
{ flag = false; break ; }
}
if(!flag)
{
flag = !next[r][1]?false:true;
for(re int i=r+1; i<=next[r][1]; i++)
{
if(sum[i][1]+sum[l][0]>0)
{ flag = false; break ; }
}
if(!flag)
{ break ; }
r = next[r][1];
continue ;
}
l = next[l][0];
}
if(!flag)
{ printf("No\n"); continue ; }
l = len1,r = len2; flag = true;
while(next[l][0]||next[r][1])
{
flag = !next[l][0]?false:true;
for(re int i=l-1; i>=next[l][0]; i--)
{
if(sum[i][0]+sum[r][1]>0)
{ flag = false; break ; }
}
if(!flag)
{
flag = !next[r][1]?false:true;
for(re int i=r-1; i>=next[r][1]; i--)
{
if(sum[i][1]+sum[l][0]>0)
{ flag = false; break ; }
}
if(!flag)
{ break ; }
r = next[r][1];
continue ;
}
l = next[l][0];
}
if(!flag)
{ printf("No\n"); }
else
{ printf("Yes\n"); }
}
return 0;
}
}
signed main()
{ return OMA::main(); }

T2

\(next\_permutation\)+\(2^{n-1}\) 50pts。

正解:

不会...

T3

直接跑两遍最短路,20pts。

乱搞:

显然刚刚的做法是假的,画个图就知道。

考虑如何让它不那么假,我们可以枚举 \(i,i\in[2,n-1]\) ,先删去 \(i\) ,即将其值赋成0,然后再正反跑两遍最短路,如果两遍最短路中都经过了当前的 \(i\) ,说明 \(i\) 是我必须要加上的点,再把当前的答案加上 \(i\) 的值即可。

最后再跑两遍不删点的最短路,比较一下答案即可。

然而好像也是假的

Code
//应该是假做法,数据太水了
#include<queue>
#include<cstdio>
#include<cstring>
#define MAX 62500
#define re register
using std::queue;
const int N = 255;
int n,m,p1[N],p2[N];
struct graph
{
int next;
int to;
}edge[MAX];
int cnt=1,head[N];
inline void add(int u,int v)
{ edge[++cnt] = (graph){head[u],v},head[u] = cnt; }
namespace SSSP
{
bool vis[MAX];
int dis[MAX],pre[MAX];
inline void spfa(int u)
{
memset(dis,0x3f,sizeof(dis));
memset(pre,0,sizeof(pre));
memset(vis,0,sizeof(vis));
queue<int>q; q.push(u);
dis[u] = p2[u]; vis[u] = true;
while(!q.empty())
{
int v = q.front(); q.pop();
vis[v] = false;
for(re int i=head[v],k; i; i=edge[i].next)
{
k = edge[i].to;
if(dis[k]>dis[v]+p2[k])
{
dis[k] = dis[v]+p2[k];
pre[k] = v;
if(!vis[k])
{ q.push(k); vis[k] = true; }
}
}
}
}
}using namespace SSSP;
namespace OMA
{
struct stream
{
template<typename type>inline stream operator >>(type &s)
{
int w=1; s=0; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*=w,*this;
}
}cin;
inline int min(int a,int b)
{ return a<b?a:b; }
signed main()
{
cin >> n >> m;
for(re int i=1; i<=n; i++)
{ cin >> p1[i]; }
for(re int i=1,u,v; i<=m; i++)
{ cin >> u >> v; add(u,v); }
int ans = MAX;
for(re int i=2; i<=n-1; i++)
{
int tmp = 0;
for(re int j=1; j<=n; j++)
{ p2[j] = p1[j]; }
p2[i] = 0;
spfa(1);
tmp += dis[n];
int u = n;
bool flag = true,jud = false;
while(pre[u])
{ if(pre[u]==i){ flag = false; } p2[u] = 0; u = pre[u]; }
p2[1] = 0;
spfa(n);
while(pre[u])
{ if(pre[u]==i&&!flag){ jud = true; tmp += p1[i]; } u = pre[u]; }
tmp += dis[1];
//ans = min(ans,tmp);
if(jud)
{ ans = min(ans,tmp); /*printf("ans=%d tmp=%d\n",ans,tmp);*/ }
}
int tmp = 0;
for(re int i=1; i<=n; i++)
{ p2[i] = p1[i]; }
spfa(1);
tmp += dis[n];
int u = n;
while(pre[u])
{ p2[u] = 0; u = pre[u]; }
p2[1] = 0;
spfa(n);
tmp += dis[1];
ans = min(ans,tmp);
printf("%d\n",ans>=MAX?-1:ans);
return 0;
}
}
signed main()
{ return OMA::main(); }

T4

不会...

noip35的更多相关文章

随机推荐

  1. 南京大学计算机基础 X64函数调用和链接器原理和可重定位的文件.o

    一. 1.函数调用差别 X64的函数调用,和X86函数调用区别,在于参数的传递不一样了,X64的参数传递不在依靠栈来传,而是寄存器,不过还是具有局限性的 比如只能允许六个寄存器来传,分别是RDI,RS ...

  2. 第二届 BJD wp(reverse和crypto)

    re 1.第一题拖入ida,flag就是直接明文摆着 2.第二题是8086的程序,拖入ida,发现有个jmp无限跳转,可能是段寄存器被修改了,ida无法将后面的汇编识别出来,所以后面才有很多无效数据, ...

  3. python使用笔记17--异常处理

    什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常. 异常是Python对象,表示一个错误. 当Pyth ...

  4. Linux账号和权限管理(第二回合)

    一.组账号文件二.添加组账号groupadd三.添加删除组成员gpasswd四.删除组账号groupdel五.查询账号信息finger六.文件/目录的权限和归属七.设置文件和目录的归属chown 一. ...

  5. .Net Core微服务——服务发现:Consul(二)

    今天有写文章的时间了,开心.延续上一篇的话题继续,顺便放上一篇的传送门:点这里. 服务调用 既然服务注册已经搞完了,那么现在就开始调用这些注册好的服务.先做一下准备动作,把consul容器跑起来: 打 ...

  6. Pytest单元测试框架之简单操作示例

    前言: Pytest是第三方单元格测试框架,更加简单,灵活,而且提供了更多丰富的扩展: Pytest与UnitTest框架的区别 UnitTest测试用例执行顺序是依照ascii码执行,而Pytest ...

  7. 微信小程序云开发-数据库和云函数的应用-点赞/收藏/评论功能

    一.准备工作 1.创建数据库表articles,字段分别为: 序号 字段名称 字段类型 字段值 字段描述 备注说明 1 title string "标题1" 文章标题   2 de ...

  8. Python自动化测试面试题-接口篇

    目录 Python自动化测试面试题-经验篇 Python自动化测试面试题-用例设计篇 Python自动化测试面试题-Linux篇 Python自动化测试面试题-MySQL篇 Python自动化测试面试 ...

  9. 在Python中执行普通除法

    如果希望Python只执行普通的除法,那么可以在程序前加上以下语句: 1 from _future_ import division 如果通过命令行(比如在Linux系统上)运行Python,可以使用 ...

  10. 关于ClassLoader 和Class的俩个记录

    public class ZFBCheckAccountTask extends TaskThread { 断点 @CallerSensitive public ClassLoader getClas ...