来自FallDream的博客,未经允许,请勿转载


奇怪的O(n)大赛,三道题数据都是几百万,真吓人。

-------------------------------------------------

A.交易♂

一个坐标轴上有n个商人,分别在坐标x1.x2..xn(保证递增且都是正整数),你和商人在同一位置的时候你可以和他交易,他在t秒后会丢下一个货物,你和货物在同一位置的时候可以拿走那个货物。移动一个单位花费时间1,捡起货物和交易不消耗时间,你一开始在0号点求拿走所有商人的货物并且走到点m(m>x)的最小时间。

n<=3000000 x,m,t<=10^9

题解:显然最优解是我们走很多段,每一段中,我们都是在走过去的时候先交易一下,然后往回走,再往前走,拿走所有货物。

用f[i]表示拿到前i个货物并且到达第i个点的最小时间,n^2dp很好列出:$$f[i]=max(f[j]+s[i]-s[j]+max(2*s[i]-2*s[j+1],t)$$

考虑优化,但是这个max怎么办呢?我们可以把它拆成两部分,一部分等待时间都是t,只需要求一个最小的坐标更新答案,另一部分我们记一下f[j]-s[j]-2*s[j+1]的最小值就行了,复杂度O(n)

我比较傻还上了一个单调队列

#include<iostream>
#include<cstdio>
#define MN 3000000
#define INF 10000000000000000LL
#define ll long long
#define getchar() (*S++)
using namespace std;
char B[1<<26],*S=B;
inline int read()
{int x = 0;  char ch = getchar();while(ch < '0' || ch > '9') ch = getchar();while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x;
}int n,q[MN+5],top,tail;
ll m,t,f[MN+5],mn=INF,s[MN+5];inline ll get1(int x,int y)
{while(top>=tail&&q[tail]<y) tail++;if(top<tail)return INF;return f[q[tail]]+t+s[x]-s[q[tail]];
}inline void ins(int x)
{while(top>=tail&&f[x]-s[x]<f[q[top]]-s[q[top]]) --top;q[++top]=x;
}int main()
{freopen("trade.in","r",stdin);freopen("trade.out","w",stdout);fread(B,1,1<<26,stdin);n=read();m=read();t=read();for(int i=1;i<=n;i++)s[i]=read();for(int i=1,j=0;i<=n;i++)    {while(j<i&&2*s[i]-2*s[j+1]>=t)mn=min(mn,f[j]-2*s[j+1]-s[j]),++j;ll res1,res2;res1=j<i?get1(i,j):INF;res2=j?mn+3*s[i]:INF;f[i]=min(res1,res2);ins(i);}printf("%lld\n",f[n]+m-s[n]);return 0;
}

B.字符串

给定两个长度都是n的字符串,你要通过一种变换使得第一个字符串变成第二个字符串,求最小变换次数。
所谓的变换是指,对于一个区间[l,r],从前往后,每个字符都可以变成上一个变成的字符,或者不变。

如果无法完成,输出-1   n<=3000000

题解:考虑贪心。我们定义一个k,初始k=n,然后从后往前对于第二个字符串中的第i位,从第一个字符串的第k位之前找一个和它相同的字符,从那个字符更新它肯定最优。

那么我们用f[i]表示第i个字符在多久之前被占用,也就是有多少个操作覆盖了它。那么每次k前移,f[i]都会+1,而每个$k\leqslant j<i$的j都要用它来更新下一个,也就是说f[j]=max(f[j],f[j+1])+1.

很显然f[j]一定不会比f[j+1]大,所以f[j]=f[j+1]+1,也就是整个数组的前半部分被我们后移了一位,然后+1  最后答案就是f的最大值.

考虑实现,后移直接用一个变量统计,+1操作通过差分实现,时间复杂度都是O(n)

#include<iostream>
#include<cstdio>
#define MN 3000000
using namespace std;
inline int read()
{int x = 0;; char ch = getchar();while(ch < '0' || ch > '9')  ch = getchar();while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x;
}int n;
int x[MN+5],now=0,move=0,ans=0;
char s[MN+5],s2[MN+5];int main()
{freopen("string.in","r",stdin);freopen("string.out","w",stdout);n=read();scanf("%s",s+1);scanf("%s",s2+1);for(register int i=n,k=n;i;i--){if(k>i&&s2[i]!=s[i]) k=i;now+=x[i+move],x[i+move]=0;if(k<=i&&s2[i]!=s[k]){while(k&&s[k]!=s2[i]) --k;if(!k) return 0*puts("-1");move++,x[k+move-1]-=1,++now;ans=max(ans,now); }}printf("%d\n",ans);return 0;
}

C.矩阵
有一个n*n的矩阵,其中有m个黑块。如果有两个块(x,y)(y,z)都是黑块,那么你可以把(z,x)涂黑。求你最多能涂黑多少块。n,m<=1000000

题解:很容易想到转化成图论模型,黑块(x,y)表示第x个点向第y个点连边。那么考虑暴力染色,将i能到的所有点染色成(col[i]+1)%3

如果存在一种合法的染色方案,且颜色012都有出现,那么此时所有点0向所有点1都有连边,1->2,2->0同理

这个很容易证明,假设你有一个图,所有0->1,1->2,2->0都有连边,那么你随意加入一个点,假设是一个0->1,那么因为所有2都向0连边,所以新加的点向所有2都有连边,那么又因为2到所有0都有连边,所以所有0到他都有连边,所以新图同样满足这个结论。而012都出现的图可以看作一个简单的0->1->2->0三个点组成的环,你把其他所有点塞进去,一定还是满足的。

如果存在一种合法的染色方案,且颜色012没有全部出现,那么此时肯定没有新增的边,这个很好理解。

如果没有合法的染色方案呢?这时候所有点向所有其他点,包括自己,肯定都有边。这个结论同样可以证明,当然也可以 打表/画图 观察发现。

严格证明我不会,但是你可以随意选出一个长度不是3的倍数的环,你会发现边都是满的。

大概就是这样,每个联通块跑一跑就没了,复杂度O(n+m)吧。

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
inline int read()
{int x = 0 , f = 1; char ch = getchar();while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;
}struct edge{int to,next,kind;}e[2000005];
int head[1000005],cnt=0,n,num,m,sum,col[1000005],cou[5];
ll ans=0;
bool mark[1000005],flag;
inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}void dfs(int x)
{mark[x]=1;num++;cou[col[x]]++;for(int i=head[x];i;i=e[i].next,++sum)if(!mark[e[i].to]) col[e[i].to]=(col[x]+((i&1)?1:-1)+3)%3,dfs(e[i].to);else if(col[e[i].to]!=(col[x]+((i&1)?1:-1)+3)%3) flag=false;
}void solve(int i)
{cou[0]=cou[1]=cou[2]=0;flag=true;num=0;sum=0;dfs(i);sum/=2;if(flag) {if(cou[0]&&cou[1]&&cou[2]) ans+=1LL*cou[0]*cou[1]+1LL*cou[2]*cou[0]+1LL*cou[1]*cou[2]-sum; }elseans+=1LL*num*num-sum;
}int main()
{freopen("matrix.in","r",stdin);freopen("matrix.out","w",stdout);n=read();m=read();for(register int i=1;i<=m;i++){int u=read(),v=read();ins(u,v);ins(v,u);}for(register int i=1;i<=n;i++)if(!mark[i]&&head[i])solve(i);printf("%lld\n",ans+m);return 0;
}

转载于:https://www.cnblogs.com/FallDream/p/liankao49.html

[4.9福建四校联考]相关推荐

  1. 2/19 福建四校联考

    1.设计图案 给你一个n*m的矩阵,每个格子必须填或者不能填,要用环和1*2的小方块填满它,求方案数. 比如3*2,每个格子都必须填 有6种填法. n*m<=300 当时一看就觉得不可做然后就放 ...

  2. NOIP模拟赛 四校联考 递推 + 分类讨论 + 树上期望

    NOIP 模拟题 题目名称兔子被子蚊子 源程序文件名rabbit.cpp quilt.cpp mosquito.cpp 输入文件名rabbit.in quilt.in mosquito.in 输出文件 ...

  3. [四校联考P3] 区间颜色众数 (主席树)

    主席树 Description 给定一个长度为 N 颜色序列A,有M个询问:每次询问一个区间里是否有一种颜色的数量超过了区间的一半,并指出是哪种颜色. Input 输入文件第一行有两个整数:N和C 输 ...

  4. [20190113]四校联考

    T1 数位DP,太菜了打挂只有10分-- Code //2019.1.14 12:25~12:47 PaperCloud #include<bits/stdc++.h> #define l ...

  5. 2017-3-19四校联考

    T1输出0有20分结果我输出1爆0(题目说精度差为整数有40%的分数,结果告诉我只能差0.5--),T2打了20分暴力,T3交了个感觉能拿50分的结果是正解--被卡常了一个点,总分110/300 T1 ...

  6. [20180826]四校联考

    T1谜题(nazo) Problem Here Solution 先把所有点的开关状态压成一个二进制数 按一个按钮就相当于异或上一个二进制数 显然不会按同一个按钮两次 枚举\(\left\lfloor ...

  7. [20180812]四校联考

    T1 消失的无向图(missing) 题目描述 从前有一张n个点的无向图,边权都是正整数.但现在所有的边都消失了,只留下任意两点之间的最短路. 你现在想知道,所有边的边权和至少是多少. ​ 输入格式 ...

  8. [20180819]四校联考

    不要问我8.19的题为什么今天才写完,因为我弱啊 T1 扫雷(mine) Problem戳这里 Solution: 显然,\(ans = min_{i=1}^n \frac{bi}{ai}\),令cn ...

  9. 4246. 【五校联考6day2】san (Standard IO)

    4246. [五校联考6day2]san (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits D ...

最新文章

  1. 设计模式实战 - 责任链模式
  2. 数据库---增删改查
  3. t分布 u分布 卡方分布_中心极限定理|z分布|t分布|卡方分布
  4. ElasticSearch-5.3.1集群环境搭建,安装ElasticSearch-head插件,安装错误解决
  5. 新工作 (2) : 准备
  6. POJ1703-Find them, Catch them
  7. Cloudera迁移scm数据库
  8. 【Scratch】《零基础入门学习Scratch》(小甲鱼)笔记一
  9. 用c语言写一个求和的程序,用C语言编写一个“等比数列求和”的程序?
  10. WPS在Excel中复选选中框复制粘贴后变成R解决办法
  11. 中国重汽:香港上市在十月
  12. 微信小程序制作水印相机
  13. layim手机版嵌入app
  14. python语言的实验心得体会范文_关于实验的心得体会范文5篇
  15. 云计算工程师面试题集锦,常见云计算面试题及答案
  16. http中的204和205
  17. 06.论Redis持久化的几种方式
  18. apache atlas
  19. 帧 计算机网络中传输数据的最小单位
  20. 广成GCAN-IO模块介绍

热门文章

  1. 真正理解、区分Action,Service和Dao功能
  2. 不能将参数 2 从“const char *”转换为“LPCWSTR”【转】http://blog.sina.com.cn/s/blog_4a94a0db0100ktxp.html...
  3. Jquery调用webService的四种方法 【转载】
  4. cvNormalizeHist()函数详解
  5. leetcode算法题--两数相加 II
  6. win7关闭开机启动项_电脑开机全是各种广告?来看看我怎么解决的吧
  7. 在asp.net2.0下配置FCKeditor
  8. 解密module_init幕后的故事
  9. Orecle基本概述(2)
  10. 我在51CTO微职位学软考——网络工程师