11.5 正睿停课训练 Day16
2018.11.5 正睿停课训练 Day16
时间:3.5h
期望得分:80~100+40+60
实际得分:80+60+60
好菜啊QAQ
A 道路规划(思路)
题意:有一张\(n\)个点的图。给定任意两点之间的最短距离,求最多可以删掉多少条边,并保证任意两点间的最短距离不变。
\(n\leq 300\)。
\(i,j\)之间的边可以删除当且仅当存在一条路径,满足\(i\)到\(j\)的最短距离为\(dis[i][j]\)。
这个路径一定是\(i\)走最短路到某个点\(k\),再从\(k\)走最短路到\(j\)。枚举一下有没有合法的\(k\)就行了啊。
//15ms 1120kb
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=305;
int dis[N][N];
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
int main()
{
int n=read(),ans=n*(n-1)>>1;
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j) dis[i][j]=read();
for(int i=1; i<=n; ++i)
for(int j=i+1; j<=n; ++j)
for(int k=1; k<=n; ++k)
if(k!=i&&k!=j&&dis[i][k]+dis[k][j]==dis[i][j])
{--ans; break;}
printf("%d\n",ans);
return 0;
}
B 逻辑判断(枚举 位运算/DP 高维前缀和)
题目链接
原题:hihoCoder挑战赛23B。
dalao位运算用的太神了orz。
\(2^n\)枚举哪t位相同,然后我们要求,能区分这t位,且其余n-t位任意的所有集合的f值。
&1就可以保证这一位保持不变了(\(0\&1=0\ 1\&1=1\)),\(\&0\)就可以保证这一位任意(\(1/0\&1=0\))。所以\(2^n\)枚举所有集合\(s\),用\(f[s]\)更新\(g[s\&t]\)就可以了。
然后\(2^n\)枚举要求的\(x\),如果\(g[x\&t]\)合法(所有都相等,且等于\(f[x]\)),就可以用\(t\)更新\(Ans[x]\)了。
于是就可以\(O(4^n)\)水过。
正解是\(O(n*3^n)\)的。以下是瞎说,可最好忽略。
用三进制表示状态,\(0/1\)表示这一位作为\(t\)位中的一位(确定),且等于\(0/1\),\(2\)表示这一位可以任意。
然后用\(n*3^n\)的DP,用\(g(s,i)\)(当前集合为\(s\),前\(i-1\)位已考虑过),推出\(f(s)\)(满足\(s\)集合的状态有多少个)。
然后再\(n*3^n\)的DP反推出答案。
这个DP就是高维前缀和。
以后再说。。
//1675ms 692kb
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=17000;
int Ans[N],f[N],g[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
int main()
{
int n=read(); const int all=(1<<n)-1;
register char c=gc(); while(!isdigit(c)) c=gc();
f[0]=c-47;
for(int i=1; i<=all; ++i) f[i]=gc()-47;
memset(Ans,0x3f,sizeof Ans);
for(int s=0; s<=all; ++s)
{
memset(g,0,sizeof g);
for(int i=0; i<=all; ++i) g[s&i]|=f[i];
int tmp=__builtin_popcount(s);
for(int i=0; i<=all; ++i) g[s&i]==f[i]&&(Ans[i]=std::min(Ans[i],tmp));
}
for(int i=0; i<=all; ++i) printf("%d ",Ans[i]);
return 0;
}
C 区间(贪心/树状数组)
题意:给定\(n\)个区间\([l_i,r_i]\)。你可以选出任意一些区间,设选出的区间个数是\(s\),\(l,r\)是这些区间的交,求\(\min(s,r-l+1)\)的最大值。
\(n\leq3\times10^5\)。
要最大化\(\min(s,r-l+1\))(\(s\)是当前区间数,\(l,r\)是区间交)。
考虑按左端点从小到大依次枚举并加入一个区间\(x\)。那么\(l\)就是\(l_x\),而\(r\)是当前选中的所有区间中最小的\(r_i\),拿个小根堆就可以维护了。
每次加入一个区间\(x\)后,若此时\(s<r-l+1\),则可以继续加入区间;若\(s>r-l+1\),可以删掉一些区间。然后更新一下答案。
删区间的时候,每次一定是删掉\(r\)最小的一个区间,把堆顶pop
掉就行了。
复杂度\(O(n\log n)\)。
把右端点的删除标记放到点上,然后用一个不断右移的指针\(R\)(右端点小于当前右指针的区间就不需要考虑了),就可以代替堆做到\(O(n)\)了。
其它做法:
二分+树状数组:对每个左端点二分区间长度,显然啊怎么就没想到啊QAQ。常数小能跑过。
不二分的树状数组:右端点位置是单调的,所以把最初做法的\(R\)用指针+树状数组维护(\(s<r-l+1\ \to\ s-Query(R-1)<R-l+1\)),保证\(R\)单调就可以了。
//195ms 4176kb
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=3e5+5;
std::priority_queue<int,std::vector<int>,std::greater<int> > q;
char IN[MAXIN],*SS=IN,*TT=IN;
struct Node
{
int l,r;
bool operator <(const Node &x)const
{
return l==x.l?r>x.r:l<x.l;
}
}A[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
int main()
{
int n=read(),ans=1;
for(int i=1; i<=n; ++i) A[i]=(Node){read(),read()};
std::sort(A+1,A+1+n);
for(int i=1; i<=n; ++i)
{
while(!q.empty()&&q.top()<=A[i].l) q.pop();
q.push(A[i].r);
if(q.size()<=ans) continue;
while(q.size()>q.top()-A[i].l+1) q.pop();
ans=std::max(ans,std::min((int)q.size(),q.top()-A[i].l+1));
}
printf("%d\n",ans);
return 0;
}
考试代码
A
暴力Dij,果然还是成功挂掉了。
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define mp std::make_pair
#define pr std::pair<int,int>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=305,M=90009;
int dis[N][N],Enum,H[N],nxt[M],to[M],len[M];
bool ok[M];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Node
{
int u,v,ds;
bool operator <(const Node &x)const
{
return ds<x.ds;
}
}A[M];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AE(int u,int v,int w)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w;
}
void Dijkstra(int *dis,int s,int n)
{
static bool vis[N];
static std::priority_queue<pr> q;
memset(vis,0,sizeof vis);
memset(dis,0x3f,(n+2)<<2);
dis[s]=0, q.push(mp(0,s));
while(!q.empty())
{
int x=q.top().second; q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if(dis[v=to[i]]>dis[x]+len[i]) q.push(mp(-(dis[v]=dis[x]+len[i]),v));
}
}
void Dijkstra2(int s,int n)
{
static bool vis[N];
static int dis[N],pre[N];
static std::priority_queue<pr> q;
memset(vis,0,(n+2)<<2);
memset(pre,0,(n+2)<<2);
memset(dis,0x3f,(n+2)<<2);
dis[s]=0, q.push(mp(0,s));
while(!q.empty())
{
int x=q.top().second; q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if(dis[v=to[i]]>dis[x]+len[i]) pre[v]=i, q.push(mp(-(dis[v]=dis[x]+len[i]),v));
}
for(int i=1; i<=n; ++i) ok[pre[i]]=ok[pre[i]^1]=1;
}
int main()
{
// freopen("ex_road3.in","r",stdin);
// freopen(".out","w",stdout);
int n=read(),cnt=0; Enum=1;
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=i; ++j) read();
for(int j=i+1; j<=n; ++j) A[++cnt]=(Node){i,j,read()};
}
std::sort(A+1,A+1+cnt);
int ans=0;
for(int i=1,u,v; i<=cnt; ++i)
{
u=A[i].u, v=A[i].v, Dijkstra(dis[u],u,n);
if(dis[u][v]!=A[i].ds) AE(u,v,A[i].ds), ++ans;
}
if(n<=100)
{
for(int i=1; i<=n; ++i) Dijkstra2(i,n);
for(int i=2; i<=Enum; i+=2) if(!ok[i]) --ans;
}
printf("%d\n",ans);
return 0;
}
B
#include <cstdio>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=17000;
int n,Ans,A[36],bit[36],fx,X;
char f[N];
int DFS0(int x,int s,int now)
{
if(x==-1) return f[now]-'0';
if(s>>x&1) return DFS0(x-1,s,now|(bit[x]<<x));
else
{
int a=DFS0(x-1,s,now);
if(a==-1) return -1;
return DFS0(x-1,s,now|(1<<x))==a?a:-1;
}
}
void DFS(int x,int s,int sum)
{
if(sum>=Ans) return;
if(x==-1)
{
DFS0(::n-1,s,0)==fx&&(Ans=std::min(Ans,sum));
return;
}
DFS(x-1,s,sum), DFS(x-1,s|(1<<A[x]),sum+1);
}
int Calc(int x,int n)
{
fx=f[X=x]-'0';
for(int cnt=0; cnt<n; bit[cnt++]=x&1,x>>=1);
std::random_shuffle(A,A+n);
Ans=n, DFS(n-1,0,0);
return Ans;
}
int main()
{
// freopen("ex_logic3.in","r",stdin);
// freopen(".out","w",stdout);
int n; scanf("%d%s",&n,f); ::n=n;
const int all=(1<<n)-1;
for(int i=0; i<n; ++i) A[i]=i;
for(int i=0; i<=all; ++i) printf("%d ",Calc(i,n));
return 0;
}
C
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=3e5+5,INF=1e9;
int n,L[N],R[N],sum[N<<1],ref[N<<1],Ans;
bool ban[N];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Node{
int l,r,id;
}A[N],B[N];
struct Segment_Tree
{
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
#define S N<<2
// int sum[S],len[S],ans[S];
#undef S
};
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
void DFS(int x,int t)
{
static int sum2[33];
if(!x)
{
int tot=0;
memcpy(sum2,sum,sizeof sum2);
for(int i=1; i<=n; ++i) tot+=((sum2[i]+=sum2[i-1])==t);
Ans=std::max(Ans,std::min(t,tot));
return;
}
DFS(x-1,t), ++sum[L[x]], --sum[R[x]+1], DFS(x-1,t+1), --sum[L[x]], ++sum[R[x]+1];
}
inline int Find(int x,int r)
{
int l=1,mid;
while(l<r)
if(ref[mid=l+r>>1]<x) l=mid+1;
else r=mid;
return l;
}
inline bool cmpA(const Node &x,const Node &y)
{
return x.l==y.l?x.r<y.r:x.l<y.l;
}
inline bool cmpB(const Node &x,const Node &y)
{
return x.r==y.r?x.l<y.l:x.r<y.r;
}
void Solve(int n)
{
int ans=std::min(n,1),now=1;
for(int i=1; i<=n; ++i)
{
while(B[now].r<A[i].l)
{
ban[B[now].id]=1;
for(int j=1,s=1,R=B[now].r; j<i; ++j)
if(!ban[A[j].id])
++s, ans=std::max(ans,std::min(s,R-A[j].l+1));
++now;
}
}
while(now<=n)
{
ban[B[now].id]=1;
for(int j=1,s=1,R=B[now].r; j<=n; ++j)
if(!ban[A[j].id])
++s, ans=std::max(ans,std::min(s,R-A[j].l+1));
++now;
}
printf("%d\n",ans);
}
int main()
{
// freopen("ex_interval3.in","r",stdin);
// freopen(".out","w",stdout);
int n=read(); ::n=n;
for(int i=1; i<=n; ++i) L[i]=read(),R[i]=read();
// if(n<=22) return DFS(n,0),printf("%d\n",Ans),0;
// int cnt=0;
// for(int i=1; i<=n; ++i) ref[++cnt]=L[i],ref[++cnt]=R[i]+1;
// std::sort(ref+1,ref+1+cnt); int t=cnt; cnt=1;
// for(int i=2; i<=t; ++i) if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
// for(int i=1; i<=n; ++i) ++sum[L[i]=Find(L[i],cnt)], --sum[R[i]=Find(R[i]+1,cnt)];
// for(int i=1; i<=n; ++i) A[i].l=B[i].r=Find(L[i],cnt), A[i].r=B[i].r=Find(R[i],cnt), A[i].id=B[i].id=i;
for(int i=1; i<=n; ++i) A[i]=B[i]=(Node){L[i],R[i],i};
std::sort(A+1,A+1+n,cmpA), std::sort(B+1,B+1+n,cmpB);
// if(n>2000) return Solve(n),0;
int ans=std::min(1,n),now=1;
for(int i=1; i<=n; ++i)
{
while(B[now].r<A[i].l)
{
ban[B[now].id]=1;
for(int j=1,s=1,R=B[now].r; j<i; ++j)
if(!ban[A[j].id])
++s, ans=std::max(ans,std::min(s,R-A[j].l+1));
++now;
}
}
while(now<=n)
{
ban[B[now].id]=1;
for(int j=1,s=1,R=B[now].r; j<=n; ++j)
if(!ban[A[j].id])
++s, ans=std::max(ans,std::min(s,R-A[j].l+1));
++now;
}
printf("%d\n",ans);
return 0;
}
11.5 正睿停课训练 Day16的更多相关文章
- 11.6 正睿停课训练 Day17
目录 2018.11.6 正睿停课训练 Day17 A chinese(思路 计数) B physics(单调队列/剪枝 DP) C chemistry(期望 DP) 考试代码 A B C 2018. ...
- 11.2 正睿停课训练 Day15
目录 2018.11.2 正睿停课训练 Day15 A 郁闷的小G(二分) B 小G的树(树形DP) C 数的距离(思路) 考试代码 B C 2018.11.2 正睿停课训练 Day15 时间:3.5 ...
- 11.1 正睿停课训练 Day14
目录 2018.11.1 正睿停课训练 Day14 A 字符串 B 取数游戏(贪心) C 魔方(模拟) 考试代码 B C 2018.11.1 正睿停课训练 Day14 时间:3.5h 期望得分:100 ...
- 10.29 正睿停课训练 Day11
目录 2018.10.29 正睿停课训练 Day11 A 线段树什么的最讨厌了(思路 DFS) B 已经没有什么好害怕的了(差分 前缀和) C 我才不是萝莉控呢(DP 贪心 哈夫曼树) 考试代码 A ...
- 10.30 正睿停课训练 Day12
目录 2018.10.30 正睿停课训练 Day12 A 强军战歌(DP 树状数组 容斥) B 当那一天来临(思路) C 假如战争今天爆发(贪心) 考试代码 B C 2018.10.30 正睿停课训练 ...
- 10.31 正睿停课训练 Day13
目录 2018.10.31 正睿停课训练 Day13 A Poker(期望) B Label(高斯消元) C Coin(二分图染色 博弈) 考试代码 A(打表) B 2018.10.31 正睿停课训练 ...
- 10.25 正睿停课训练 Day9
目录 2018.10.25 正睿停课训练 Day9 A 数独(思路 DP) B 红绿灯(最短路Dijkstra) C 轰炸(计算几何 圆并) 考试代码 B C 2018.10.25 正睿停课训练 Da ...
- 10.24 正睿停课训练 Day8 AM
目录 2018.10.24 正睿停课训练 Day8 AM A 棒棒糖(组合) B 彩虹糖(思路 博弈) C 泡泡糖(DP) 考试代码 A B C 2018.10.24 正睿停课训练 Day8 AM 期 ...
- 10.23 正睿停课训练 Day7
目录 2018.10.23 正睿停课训练 Day7 A 矩形(组合) B 翻转(思路) C 求和(思路 三元环计数) 考试代码 B1 B2 C 2018.10.23 正睿停课训练 Day7 期望得分: ...
随机推荐
- Docker容器数据卷
⒈Docker容器中数据如何持久化? ①通过commit命令使容器反向为镜像 ②以容器数据卷的方式将数据抽离 ⒉容器数据卷的作用? ①容器数据的持久化 ②容器间继承.共享数据 ⒊能干嘛? 卷就是目录或 ...
- GCC编译过程与动态链接库和静态链接库
1. 库的介绍 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可 ...
- freeRTOS中文实用教程5--内存管理
1.前言 不同的嵌入式系统具有不同的内存配置和时间要求.所以单一的内存分配算法只可能适合部分应用程序. FreeRTOS 将内存分配作为可移植层面(相对于基本的内核代码部分而言).这使得不同的应用程序 ...
- freeRTOS中文实用教程3--中断管理之中断嵌套
1.前言 最新的 FreeRTOS 移植中允许中断嵌套.中断嵌套需要在 FreeRTOSConfig.h 中设置configKERNEL_INTERRUPT_PRIORITY 和configMAX_S ...
- 【转】OpenCV—imread读取数据为空
之前遇到一个很郁闷的问题,因为从用OpenCV2.3.1改成OpenCV2.4.4,开始改用Mat和imread来代替Iplimage和cvLoadImage,出了点小问题:imread读入数据总是为 ...
- SharePoint 2010:搜索服务当前处于脱机状态
错误 搜索服务当前处于脱机状态.请访问 SharePoint 管理中心中的"服务器上的服务"页,以验证是否启用了该服务.这也可能是由于正在移动索引器所致. 正在配置网站集搜索关 ...
- VC++常用数据类型
原文地址:https://www.cnblogs.com/yincheng01/archive/2008/12/31/2213386.html 一. VC常用数据类型列表 二 ...
- Androi:ViewPager
Android ViewPager控件的使用(基于ViewPager的横向相册)!!!: http://blog.csdn.net/Android_Tutor/article/details/7980 ...
- Transformer+BERT+GPT+GPT2
Transformer: https://jalammar.github.io/illustrated-transformer/ BERT: https://arxiv.org/pdf/1810.04 ...
- Oracle基本命令大全
用户: scott/tiger sys as sysdba 空密码 转换用户登录: connect 用户/密码 connect sys as sysdba 权限 用户解锁: alter user ...