A. The Motorway

等价于找到最小和最大的$L$满足存在$S$使得$S+(i-1)L\leq a_i\leq S+i\times L$

$S\leq\min((1-i)L+a_i)$

$S\geq\max(-i\times L+a_i)$

求出上下凸壳的交点即可,因为斜率本身有序,故时间复杂度为$O(n)$。

#include<cstdio>
const int N=1000010,BUF=12000000;
const double inf=1e30,eps=1e-9;
char Buf[BUF],*buf=Buf;
int n,i,j,b[N],ka[N],kb[N],qa[N],ta,qb[N],tb;
double ansl=inf,ansr=-inf,pre,A,B,ca[N],cb[N];
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
inline int sgn(double x){
if(x>eps)return 1;
if(x<-eps)return -1;
return 0;
}
inline double posa(int x,int y){return 1.0*(b[y]-b[x])/(ka[x]-ka[y]);}
inline double posb(int x,int y){return 1.0*(b[y]-b[x])/(kb[x]-kb[y]);}
inline double posab(int x,int y){
if(ka[x]==kb[y])return 1e100;
return 1.0*(b[y]-b[x])/(ka[x]-kb[y]);
}
inline void work(int x,int y,double now){
double o=posab(qa[x],qb[y]);
if(sgn(o-pre)>=0&&sgn(o-now)<=0){
if(o<ansl)ansl=o;
if(o>ansr)ansr=o;
}
pre=now;
}
int main(){
fread(Buf,1,BUF,stdin);read(n);
for(i=1;i<=n;i++)read(b[i]),ka[i]=1-i,kb[i]=-i;
for(i=1;i<=n;qa[++ta]=i++)while(ta>1&&posa(qa[ta-1],qa[ta])>posa(qa[ta],i))ta--;
for(i=n;i;qb[++tb]=i--)while(tb>1&&posb(qb[tb-1],qb[tb])>posb(qb[tb],i))tb--;
for(i=1;i<ta;i++)ca[i]=posa(qa[i],qa[i+1]);
for(i=1;i<tb;i++)cb[i]=posb(qb[i],qb[i+1]);
ca[ta]=cb[tb]=inf;
i=j=1,pre=-inf;
while(i<=ta&&j<=tb){
A=ca[i],B=cb[j];
if(!sgn(A-B))work(i++,j++,A);
else if(A<B)work(i++,j,A);
else work(i,j++,B);
}
return printf("%.12f %.12f",ansl,ansr),0;
}

  

B. Bytehattan

在平面图中,两个点不连通等价于在对偶图中两个点连通,并查集维护。

#include<cstdio>
int n,k,i,x,y,a,b,f[2250000],t;char op,s[100];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
inline int P(int x,int y){return !x||x==n||!y||y==n?0:(x-1)*(n-1)+y;}
int main(){
read(n),read(k);
for(i=1;i<n*n;i++)f[i]=i;
while(k--){
read(x),read(y);while(!(((op=getchar())=='N')||(op=='E')));
if(t){read(x),read(y);while(!(((op=getchar())=='N')||(op=='E')));}else gets(s);
a=op=='N'?P(x-1,y):P(x,y-1);b=P(x,y);
if(F(a)==F(b))t=1,puts("NIE");else t=0,f[f[a]]=f[b],puts("TAK");
}
return 0;
}

  

C. The Carpenter

两个三角形之间必然存在一条横的或者竖的或者斜$45$度的分割线,求出每条分割线两侧的最优解即可。

时间复杂度$O(nm)$。

D. Demonstrations

离散化后用并查集染色维护出每一段被哪几个区间覆盖,然后枚举每段更新答案即可。

#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
const int N=1000010;
int n,m,i,a[N],e[N][2],f[N],cnt[N],g[N][2],val[N],ans;map<int,int>T[N];
int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
inline void col(int l,int r,int x){
l=lower_bound(a+1,a+m+1,l)-a;
while(1){
l=F(l);
if(a[l]>=r)return;
cnt[l]++;
if(cnt[l]>2)f[l]++;
else g[l][cnt[l]-1]=x;
l++;
}
}
int main(){
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d",&e[i][0],&e[i][1]);
a[++m]=e[i][0];
a[++m]=e[i][1];
}
sort(a+1,a+m+1);
for(i=1;i<=m;i++)f[i]=i;
for(i=1;i<=n;i++)col(e[i][0],e[i][1],i);
for(i=1;i<m;i++){
int x=g[i][0],y=g[i][1],z=a[i+1]-a[i];
if(cnt[i]==1)val[x]+=z;
if(cnt[i]==2)T[x][y]+=z;
}
for(i=1;i<m;i++){
int x=g[i][0],y=g[i][1],z=a[i+1]-a[i];
if(cnt[i]==2)ans=max(ans,val[x]+val[y]+T[x][y]);
}
sort(val+1,val+n+1);
ans=max(ans,val[n-1]+val[n]);
printf("%d",ans);
}

  

E. The Exam

按$n$奇偶性构造出相邻差值最大的序列然后判断是否不小于$k$即可,时间复杂度$O(n)$。

#include<cstdio>
const int N=1000010,OUT=10000000;
int n,m,k,i,j,x,y,w[N],a[N];char Out[OUT],*ou=Out;int Outn[30],Outcnt;
inline void write(int x){
if(!x)*ou++=48;
else{
for(Outcnt=0;x;x/=10)Outn[++Outcnt]=x%10+48;
while(Outcnt)*ou++=Outn[Outcnt--];
}
}
inline int abs(int x){return x>0?x:-x;}
int main(){
scanf("%d%d",&n,&k);
for(i=0;i<n;i++)w[i]=i+1;
if(n&1){
m=n/2;
for(i=j=m;i<n;i++)if(w[i]-w[i-m]<w[j]-w[j-m])j=i;
x=j,y=(x+m)%n;
for(i=0;i<n;i+=2,x=(x+n-1)%n)a[i]=x;
for(i=1;i<n;i+=2,y=(y+n-1)%n)a[i]=y;
}else{
for(i=1,j=0;i<n;i+=2,j++)a[i]=j;
for(i=0;i<n;i+=2,j++)a[i]=j;
}
for(i=1;i<n;i++)if(abs(w[a[i]]-w[a[i-1]])<k)return puts("NIE"),0;
for(i=0;i<n;i++)write(w[a[i]]),*ou++=' ';
fwrite(Out,1,ou-Out,stdout);
return 0;
}

  

F. Speed Cameras

不断剥叶子得出每个点的层次,那么前$\lfloor\frac{k}{2}\rfloor$层必选,若$k$为奇数则还要多选一个点。

#include<cstdio>
const int N=1000010;
int n,m,k,i,x,y,deg[N],d[N],g[N],v[N<<1],nxt[N<<1],ed,h,t,q[N],ans,vis[N];
inline void add(int x,int y){deg[x]++;v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
inline void ext(int x,int y){
deg[x]--;
if(deg[x]>1)return;
if(!d[x])d[q[++t]=x]=y;
}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
for(h=i=1;i<=n;i++)if(deg[i]<=1)ext(i,1);
while(h<=t){
x=q[h++];
for(i=g[x];i;i=nxt[i])ext(v[i],d[x]+1);
}
for(i=1;i<=n;i++)if(d[i]*2<=m)vis[i]=1;
for(i=1;i<=n;i++)if(!vis[i]&&(m&1)){vis[i]=1;break;}
for(i=1;i<=n;i++)if(vis[i])ans++;
printf("%d\n",ans);
for(i=1;i<=n;i++)if(vis[i])printf("%d ",i);
}

  

G. Game

若$0$只有$1$个,那么显然无解。

若$0$超过$1$个,那么显然有解。

若$2,3,5,7$这些质数出现次数为奇数,那么显然无解。

那么将剩下每个数出现次数不断减$2$直到$\leq 6$都不会影响结果。

设$f[i][j][k]$表示质数$2$的指数为$i$,$3$的指数为$j$,选了$k$个数是否可能,bitset优化DP即可。

#include<cstdio>
typedef long long ll;
const int lim=6;
int Case,i,j,x,y;ll a[10];
unsigned long long f[lim*7+1][lim*4+1];
bool solve(){
if(a[0]==1)return 0;
if(a[0]>1)return 1;
if(a[5]&1)return 0;
a[5]=0;
if(a[7]&1)return 0;
a[7]=0;
ll c2=a[2]+a[4]*2+a[6]+a[8]*3;
if(c2&1)return 0;
ll c3=a[3]+a[6]+a[9]*2;
if(c3&1)return 0;
for(i=0;i<=lim*7;i++)for(j=0;j<=lim*4;j++)f[i][j]=0;
f[0][0]=1;
int s2=0,s3=0,s=0;
for(i=0;i<10;i++){
if(a[i]>lim)a[i]-=(a[i]-lim)/2*2;
while(a[i]>lim)a[i]-=2;
if(!a[i])continue;
int A=0,B=0;
if(i==2)A=1;
if(i==3)B=1;
if(i==4)A=2;
if(i==6)A=B=1;
if(i==8)A=3;
if(i==9)B=2;
for(j=0;j<a[i];j++){
s2+=A,s3+=B,s++;
for(x=lim*7;x>=A;x--)for(y=lim*4;y>=B;y--)f[x][y]|=f[x-A][y-B]<<1;
}
}
return f[s2/2][s3/2]>>(s/2)&1;
}
int main(){
scanf("%d",&Case);
while(Case--){
for(i=0;i<10;i++)scanf("%lld",&a[i]);
puts(solve()?"TAK":"NIE");
}
}

  

H. The Hero

将每个点按存在时间段拆点,共$O(n+p)$个点。

进行Dijkstra求最短路,对于每个拆出来的点枚举所有出边进行松弛。

同时对于每个点维护所有拆点集合set,每次用$l$松弛距离时将其从set中删除。

时间复杂度$O(10(n+q)\log n)$。

#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<ll,int>P;
const int N=100010,M=1000010;
const ll inf=1LL<<60;
const int BUF=40000000;
char Buf[BUF],*buf=Buf;
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
inline void read(ll&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
int n,m,cnt,i,j,k,x,y,z,g[N],v[M],w[M],nxt[M],ed,st[N],en[N];
bool vis[N<<1];
struct E{
int x;ll l,r;
E(){}
E(int _x,ll _l,ll _r){x=_x,l=_l,r=_r;}
}e[N],p[N<<1];
set<P>T[N];
ll d[N<<1],ans=inf;
priority_queue<P,vector<P>,greater<P> >q;
inline bool cmp(const E&a,const E&b){
if(a.x!=b.x)return a.x<b.x;
return a.l<b.l;
}
inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
inline void ext(int x,ll y){
if(y>p[x].r)return;
if(vis[x])return;
if(y>=d[x])return;
d[x]=y;
q.push(P(y,x));
}
inline void work(ll R,ll dis,int x,int len){
dis+=len;
set<P>::iterator it=T[x].lower_bound(P(dis,0));
if(it==T[x].end())return;
if(p[it->second].l<=dis)ext(it->second,dis),it++;
while(it!=T[x].end()){
if(p[it->second].l-len>R)return;
ext(it->second,p[it->second].l);
set<P>::iterator nxt=it;
nxt++;
T[x].erase(it);
it=nxt;
}
}
int main(){
fread(Buf,1,BUF,stdin);
read(n),read(m);
while(m--)read(x),read(y),read(z),add(x,y,z);
read(m);
for(i=1;i<=m;i++)read(e[i].x),read(e[i].l),read(e[i].r);
sort(e+1,e+m+1,cmp);
for(i=1;i<=m;i=j){
for(j=i;j<=m&&e[i].x==e[j].x;j++);
ll pre=0;
x=e[i].x;
st[x]=cnt+1;
for(k=i;k<j;k++){
if(e[k].l>pre+1)p[++cnt]=E(x,pre+1,e[k].l-1);
pre=max(pre,e[k].r);
}
p[++cnt]=E(x,pre+1,inf);
en[x]=cnt;
}
for(i=1;i<=n;i++)if(!st[i]){
p[++cnt]=E(i,1,inf);
st[i]=en[i]=cnt;
}
for(i=1;i<=cnt;i++)d[i]=inf;
for(i=1;i<=n;i++)for(j=st[i];j<=en[i];j++)T[i].insert(P(p[j].r,j));
ext(st[1],1);
while(!q.empty()){
P t=q.top();q.pop();
if(vis[t.second])continue;
vis[t.second]=1;
for(i=g[p[t.second].x];i;i=nxt[i])work(p[t.second].r,t.first,v[i],w[i]);
}
for(i=st[n];i<=en[n];i++)ans=min(ans,d[i]);
if(ans>=inf)puts("NIE");else printf("%lld",ans-1);
}

  

I. Genetic Engineering

设$f[i]$表示以$i$为开头一段的结尾最多能有多少段,$g[i]$表示以$i$为开头一段的开头最多能有多少段。

则$f[i]=\max(g[>i])+1,g[i]=f[i后面第k个和i数值相同的位置]$。

若有多个最大值,选数值最小的,再有多个选下标最靠前的,这样可以满足字典序最小。

时间复杂度$O(n)$。

#include<cstdio>
#include<vector>
using namespace std;
const int N=1000010;
int n,m,i,rk[N],a[N],f[N],g[N],nxt[N],mx,pos;
vector<int>v[N];
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
v[a[i]].push_back(i);
rk[i]=v[a[i]].size()-1;
}
mx=0,pos=n+1;
for(i=n;i;i--){
f[i]=mx+1;
nxt[i]=pos;
if(rk[i]+m-1<v[a[i]].size()){
g[i]=f[v[a[i]][rk[i]+m-1]];
if(g[i]>mx||g[i]==mx&&a[i]<=a[pos])mx=g[i],pos=i;
}
}
printf("%d\n",mx*m);
while(mx--){
for(i=1;i<=m;i++)printf("%d ",a[pos]);
pos=nxt[v[a[pos]][rk[pos]+m-1]];
}
}

  

J. Robin Hood

$ans=\sum_{i=1}^n i-2^{\lfloor\log_2i\rfloor}$,数位DP求出每种$\log$的$i$的个数即可。

#include<cstdio>
const int N=50;
int n,i,j,k,nj,x,m,a[N];long long ans,f[N][2][N];
int main(){
scanf("%d",&n);
m=40;
ans=1LL*n*(n+1)/2;
for(i=1;i<=m;i++)a[i]=n&1,n>>=1;
f[m][0][0]=1;
for(i=m;i>1;i--)for(j=0;j<2;j++)for(k=0;k<=m;k++)for(x=0;x<2;x++){
nj=j;
if(!j){
if(x>a[i-1])continue;
if(x<a[i-1])nj=1;
}
f[i-1][nj][x?(k?k:(i-1)):k]+=f[i][j][k];
}
for(j=0;j<2;j++)for(k=1;k<=m;k++)ans-=f[1][j][k]<<(k-1);
printf("%lld",ans);
}

  

K. Blanket

扫描线+线段树统计出每个方格被经过的矩形数目的平方和即可,时间复杂度$O(n\log n)$。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=400010,M=1200000;
int n,m,i,X,Y,A,B,ca,ce,a[N],w[M],tag[M];ll wv[M],wvv[M];long double ans;
struct E{int x,l,r,t;E(){}E(int _x,int _l,int _r,int _t){x=_x,l=_l,r=_r,t=_t;}}e[N];
inline bool cmp(const E&a,const E&b){return a.x<b.x;}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
void build(int x,int a,int b){
w[x]=::a[b]-::a[a];
if(a+1>=b)return;
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid,b);
}
inline void tag1(int x,int p){
wvv[x]+=2LL*p*wv[x]+1LL*p*p*w[x];
wv[x]+=1LL*p*w[x];
tag[x]+=p;
}
void change(int x,int a,int b,int c,int d,int p){
if(c<=a&&b<=d){tag1(x,p);return;}
if(tag[x])tag1(x<<1,tag[x]),tag1(x<<1|1,tag[x]),tag[x]=0;
int mid=(a+b)>>1;
if(c<mid)change(x<<1,a,mid,c,d,p);
if(d>mid)change(x<<1|1,mid,b,c,d,p);
wv[x]=wv[x<<1]+wv[x<<1|1];
wvv[x]=wvv[x<<1]+wvv[x<<1|1];
}
int main(){
read(n);read(A),read(B);
for(i=1;i<=n;i++){
read(X),read(Y);
if(!A||!B)continue;
ans-=1LL*A*B;
a[++ca]=Y;
a[++ca]=Y+B;
e[++ce]=E(X,Y,Y+B,1);
e[++ce]=E(X+A,Y,Y+B,-1);
}
sort(e+1,e+ce+1,cmp);
sort(a+1,a+ca+1);
for(i=1;i<=ca;i++)if(i==1||a[i]!=a[i-1])a[++m]=a[i];
build(1,1,m);
for(i=1;i<=ce;i++){
if(i>1&&e[i].x>e[i-1].x)ans+=1.0*wvv[1]*(e[i].x-e[i-1].x);
change(1,1,m,lower_bound(a+1,a+m+1,e[i].l)-a,lower_bound(a+1,a+m+1,e[i].r)-a,e[i].t);
}
return printf("%.15f",(double)(ans/n/(n-1))),0;
}

  

XIV Open Cup named after E.V. Pankratiev. GP of Europe的更多相关文章

  1. XIV Open Cup named after E.V. Pankratiev. GP of SPb

    A. Bracket Expression 直接按题意模拟即可. 时间复杂度$O(n)$. #include<stdio.h> #include<algorithm> #inc ...

  2. XIV Open Cup named after E.V. Pankratiev. GP of America

    A. Ancient Diplomacy 建图,同色点间边权为$0$,异色点间边权为$1$,则等价于找一个点使得到它最短路最长的点的最短路最小,Floyd即可. 时间复杂度$O(n^3)$. #inc ...

  3. XV Open Cup named after E.V. Pankratiev. GP of Tatarstan

    A. Survival Route 留坑. B. Dispersed parentheses $f[i][j][k]$表示长度为$i$,未匹配的左括号数为$j$,最多的未匹配左括号数为$k$的方案数. ...

  4. XVII Open Cup named after E.V. Pankratiev. GP of SPb

    A. Array Factory 将下标按前缀和排序,然后双指针,维护最大的右边界即可. #include<cstdio> #include<algorithm> using ...

  5. XVI Open Cup named after E.V. Pankratiev. GP of Ukraine

    A. Associated Vertices 首先求出SCC然后缩点,第一次求出每个点能到的点集,第二次收集这些点集即可,用bitset加速,时间复杂度$O(\frac{nm}{64})$. #inc ...

  6. XVI Open Cup named after E.V. Pankratiev. GP of Peterhof

    A. (a, b)-Tower 当指数大于模数的时候用欧拉定理递归计算,否则直接暴力计算. #include<cstdio> #include<algorithm> #incl ...

  7. XVI Open Cup named after E.V. Pankratiev. GP of Siberia

    A. Passage 枚举两个点,看看删掉之后剩下的图是否是二分图. #include <bits/stdc++.h> using namespace std ; const int MA ...

  8. XVI Open Cup named after E.V. Pankratiev. GP of Ekaterinburg

    A. Avengers, The 留坑. B. Black Widow 将所有数的所有约数插入set,然后求mex. #include<bits/stdc++.h> using names ...

  9. XVI Open Cup named after E.V. Pankratiev. GP of Eurasia

    A. Nanoassembly 首先用叉积判断是否在指定向量右侧,然后解出法线与给定直线的交点,再关于交点对称即可. #include<bits/stdc++.h> using names ...

随机推荐

  1. Mysql相关知识点梳理(一):优化查询

    EXPLAIN解析SELECT语句执行计划: EXPLAIN与DESC同义,通过它可解析MySQL如何处理SELECT,提供有关表如何联接和联接的次序,还可以知道什么时候必须为表加入索引以得到一个使用 ...

  2. 什么是javabean及其用法(转)

    因工作需要 需要学习jsp方面的知识 这篇博客文章写得比较全面 我记录下: 一.什么是JavaBean JavaBean是一个遵循特定写法的Java类,它通常具有如下特点: 这个Java类必须具有一个 ...

  3. volative 与处理器的嗅探技术

    在<java并发编程的艺术>这本书中,关于volatile的内存原理本质的描述如下: 有volatile变量修饰共享变量在编译器编译后,后多出一个“lock” 来(lock前缀指令相当于一 ...

  4. mysql 分库分表 ~ ShardingSphere生态圈

    一  简介   Apache ShardingSphere是一款开源的分布式数据库中间件组成的生态圈二 成员包含   Sharding-JDBC是一款轻量级的Java框架,在JDBC层提供上述核心功能 ...

  5. LeetCode第十题-正则表达式匹配

    Regular Expression Matching 问题简介:给定字符串,给定匹配模式,判断字符串是否满足匹配模式 问题详解:一共有两种特殊模式: ‘.’ 匹配任何单个字符 ‘*’ 匹配前面元素的 ...

  6. Python爬虫从入门到进阶(1)之Python概述及爬虫入门

    一.Python 概述 1.计算机语言概述 (1).语言:交流的工具,沟通的媒介 (2).计算机语言:人跟计算机交流的工具 (3).Python是计算机语言的一种 2.Python编程语言 代码:人类 ...

  7. Centos6.X搭建Squid为YUM做代理

    1.在能联网的机器上安装 Squid yum install squid 2.配置squid vi /etc/squid/squid.conf 编辑内容如下: http_port cache_mem ...

  8. 【原创】大数据基础之ElasticSearch(5)重要配置及调优

    Index Settings 重要索引配置 Index level settings can be set per-index. Settings may be: 1 static 静态索引配置 Th ...

  9. Java框架中Struts和Struts2框架的区别

    struts1 与 struts2 的区别:1.都是 MVC 的 WEB 框架,2 struts1的老牌框架,应用很广泛,有很好的群众基础,使用它开发风险很小,成本更低!struts2虽然基于这个框架 ...

  10. java 根据Url下载对应的文件到指定位置,读txt文件获取url

    package test; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; im ...