【题解】Informacije [COCI2012]

传送门:官方题面

【题目描述】

有一个长度为 \(n\) 的 序列 \(a\)(由 \([1,n]\) 中的数组成,且每个数只会出现一次),现给出两个整数 \(n,m\) 和 \(m\) 个关于 \(a\) 的描述,格式如下:

\(1\ l\ r\ v\) 表示 \(max\{a[l],a[l+1]...a[r]\}=v\),

\(2\ l\ r\ v\) 表示 \(min\{a[l],a[l+1]...a[r]\}=v\)。

请输出一个满足上面 \(m\) 个描述的序列,如果多种答案,输出任意一种,无解则输出 \(-1\)。

【样例】

  1. 样例输入:
  2. 3 2
  3. 1 1 1 1
  4. 2 2 2 2
  5. 样例输出:
  6. 1 2 3
  7. 样例输入:
  8. 4 2
  9. 1 1 1 1
  10. 2 3 4 1
  11. 样例输出:
  12. -1
  13. 样例输入:
  14. 5 2
  15. 1 2 3 3
  16. 2 4 5 4
  17. 样例输出:
  18. 1 2 3 4 5

【数据范围】

\(100 \%:\) \(1 \leqslant n \leqslant 200,\) \(0 \leqslant m \leqslant 40000\)


【分析】

\(n \leqslant 200\),一开始只是觉得可以写 \(n^3\) 的算法,比如矩阵乘法之类的,但看到 \(m \leqslant 40000\) 时,瞬间想到建一张完全图跑图论。事实证明这一直觉是正确的。

用 \(pan[i][j]\) 表示整数 \(i\) 是否可以填在 \(j\) 这个位置(只需要满足给出的 \(m\) 个条件即可)。

如果 \(pan[i][j]\) 为 \(1\),那么 \(i\) 向 \(j\) 连一条有向边,然后跑一遍二分图最大匹配,\(match\) 数组即为答案。

匈牙利算法的时间复杂度为:\(O(|V|*|E|)\),其中 \(|E| \leqslant |V|^2\),\(200\) 个点的完全图完全不是问题。

如何求 \(pan\) 数组?

最开始 \(yy\) 了一种 \(mn\) 的预处理方法:

\((1).\) \(Lw[x],Rw[x]\) 分别表示整数 \(x\) 必须要放的位置所在区间左右端点。

对于所有的 \(l,r,v\),\(Lw[v]=max\{l,Lw[v]\},Rw[v]=min\{r,Rw[v]\}\)。

\((2).\) \(Ls[i],Rs[i]\) 分别表示位置 \(i\) 可放置的整数范围。

对于 \(1,l,r,v\),\(Rs[i]=min\{v,Rs[i]\} (i \in [l,r])\),

对于 \(2,l,r,v\),\(Ls[i]=max\{v,Ls[i]\} (i \in [l,r])\)。

但仔细想想觉得不太对,所以就改成了 \(mn^2\) 的暴力枚举,本以为会超时,结果加了剪枝后居然轻松跑过了。

后来发现官方题解给的就是 \(mn\) 的做法,而且和我之前想的一模一样。。。

【Code】

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdlib>
  5. #include<cstdio>
  6. #define Re register int
  7. using namespace std;
  8. const int N=203,M=40003,inf=2e9;
  9. int n,m,op[M],L[M],R[M],val[M],pan[N][N];
  10. int o,ans,vis[N],head[N],match[N];
  11. struct QAQ{int to,next;}a[N*N];
  12. inline void add(Re x,Re y){a[++o].to=y,a[o].next=head[x],head[x]=o;}
  13. inline void in(Re &x){
  14. int f=0;x=0;char c=getchar();
  15. while(c<'0'||c>'9')f|=c=='-',c=getchar();
  16. while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
  17. x=f?-x:x;
  18. }
  19. inline int judge(Re i,Re L,Re R){//判断在[L,R]这个区间内是否有1
  20. for(Re j=L;j<=R;++j)if(pan[i][j])return 1;
  21. return 0;
  22. }
  23. inline void add_(Re i,Re L,Re R){//将[L,R]全部变为0
  24. for(Re j=L;j<=R;++j)pan[i][j]=0;
  25. }
  26. inline void add(Re i,Re L,Re R){//将[L,R]以外的全部变为0
  27. for(Re j=1;j<L;++j)pan[i][j]=0;
  28. for(Re j=R+1;j<=n;++j)pan[i][j]=0;
  29. }
  30. inline void Print(){
  31. for(Re i=1;i<=n;++i){
  32. printf("pan[%d]: ",i);
  33. for(Re j=1;j<=n;++j)if(pan[i][j])printf("%d ",j);
  34. puts("");
  35. }
  36. puts("");
  37. }
  38. inline int sakura(){
  39. for(Re i=1;i<=m;++i){
  40. if(op[i]>1){//L[i]~R[i]的最小值为val[i]
  41. if(!judge(val[i],L[i],R[i]))return 0;
  42. add(val[i],L[i],R[i]);
  43. for(Re j=1;j<val[i];++j){//比val小的数
  44. Re flag1=judge(j,1,L[i]-1),flag2=judge(j,R[i]+1,n);
  45. if(!flag1&&!flag2)return 0;//如果没有可放的位置就直接return
  46. else if(flag1&&!flag2)add(j,1,L[i]-1);//删掉左边
  47. else if(flag2&&!flag1)add(j,R[i]+1,n);//删掉右边
  48. else add_(j,L[i],R[i]);//删掉左右两边
  49. }
  50. }
  51. else{//L[i]~R[i]的最大值为val[i]
  52. if(!judge(val[i],L[i],R[i]))return 0;
  53. add(val[i],L[i],R[i]);
  54. for(Re j=val[i]+1;j<=n;++j){//比val大的数
  55. Re flag1=judge(j,1,L[i]-1),flag2=judge(j,R[i]+1,n);
  56. if(!flag1&&!flag2)return 0;
  57. else if(flag1&&!flag2)add(j,1,L[i]-1);
  58. else if(flag2&&!flag1)add(j,R[i]+1,n);
  59. else add_(j,L[i],R[i]);
  60. }
  61. }
  62. }
  63. return 1;//最后还要return 1
  64. }
  65. inline int dfs(Re x){
  66. for(Re i=head[x],to;i;i=a[i].next)
  67. if(!vis[to=a[i].to]){
  68. vis[to]=1;
  69. if(!match[to]||dfs(match[to])){
  70. match[to]=x;return 1;
  71. }
  72. }
  73. return 0;
  74. }
  75. int main(){
  76. // freopen("informacije.in","r",stdin);
  77. // freopen("informacije.out","w",stdout);
  78. in(n),in(m);
  79. for(Re i=1;i<=m;++i)in(op[i]),in(L[i]),in(R[i]),in(val[i]);
  80. for(Re i=1;i<=n;++i)
  81. for(Re j=1;j<=n;++j)
  82. pan[i][j]=1;
  83. if(!sakura())puts("-1");
  84. else{
  85. // Print();
  86. for(Re i=1;i<=n;++i)
  87. for(Re j=1;j<=n;++j)
  88. if(pan[i][j])add(i,j);
  89. for(Re i=1;i<=n;++i){
  90. memset(vis,0,sizeof(vis));
  91. if(!dfs(i))return !puts("-1");
  92. }
  93. for(Re i=1;i<=n;++i)printf("%d ",match[i]);
  94. }
  95. fclose(stdin);
  96. fclose(stdout);
  97. return 0;
  98. }

【题解】Informacije [COCI2012]的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. powershell 提取 spotlight 图片

    powershell脚本来源于网络,有一些调整. # 将复制出来的缓存图片保存在下面的文件夹 $dir = Split-Path -Parent $MyInvocation.MyCommand.Def ...

  2. git报错:failed to push some refs to 'git@github.com:JiangXiaoLiang1988/CustomerHandl

    一.错误信息 今天在使用git将代码上传到GitHub的时候报下面的错误: 以前上传代码的时候重来没有出现这种错误,在网上查找了半天终于找到原因了:github中的README.md文件不在本地代码目 ...

  3. MVC教程:MVC区域路由

    一.区域路由 为了管理网站中大量的文件,在ASP.NET MVC 2.0版本中引入了一个新概念:区域(Area). 有了区域以后,可以让我们的项目不至于太复杂而导致管理混乱.每个模块的页面都放入相应的 ...

  4. StreamWriter StreamReader

    private void WriteLoginJsonData(object jsonData) { using (FileStream writerFileStream = new FileStre ...

  5. python验证码识别(2)极验滑动验证码识别

    目录 一:极验滑动验证码简介 二:极验滑动验证码识别思路 三:极验验证码识别 一:极验滑动验证码简介   近些年来出现了一些新型验证码,不想旧的验证码对人类不友好,但是这种验证码对于代码来说识别难度上 ...

  6. ADB控制手机命令(adb命令)

    手机端配置tcp方式连接 su setprop service.adb.tcp.port 5555 stop adbd start adbd 首先使用管理员权限,然后打开监听5555端口 电脑端使用a ...

  7. 解决iOS地图持续定位耗电问题

    地图位置刷新的代理didUpdateLocations会持续调用,手机非常耗电 但是在实际开发中,有一些APP确实需要用到持续定位的功能,比如:运动类, 导航类, 天气类等等 如何进行持续定位呢?保证 ...

  8. SparkStreaming wordCountDemo基础案例

    体现sparkStreaming的秒级准实时性,所以我们需要一个能够持续输入数据的东东 1.CentOS上下载nc 创建一个scala工程,导入相关pom依赖 <?xml version=&qu ...

  9. [20190522]How to get dump or list parameters set at session level.txt

    [20190522]How to get dump or list parameters set at session level.txt 1.环境:SCOTT@book> @ ver1PORT ...

  10. SRDC - ORA-1555: Query Duration 0: Checklist of Evidence to Supply (Doc ID 1682704.1)

    SRDC - ORA-1555: Query Duration 0: Checklist of Evidence to Supply (Doc ID 1682704.1) Action Plan 1. ...