A. 争夺圣杯

还是想说一下,这题是原题啊...想做的人可以戳codechef上的MTMXSUM(懒得贴链接了,套了个壳,不过正常人应该都能看得出来)

显然异或输出没什么奇怪的性质...

考虑一个元素a[x]在哪些区间中会成为最大值,我们可以用单调栈找出前面比这个元素大的第一个元素a[l],右边大的第一个元素a[r]。

考虑这个元素对每一长度的贡献,设p=x-l,q=r-x,那么对于区间[s,t],只有当l<s<=x,x<=t<r,只有这pq个区间最大值为a[x]。

那么考虑这些区间的长度,不妨设p<=q,那么可以根据区间长度跟p、q的关系来统计答案。

当1<=len<=p时,显然共有len个区间(因为x肯定要在区间内)。

当p<len<=q时,共有p个区间(因为左端点可以是l+1~x)

当q<len<=p+q-1时,共有p+q-len个([x-p+1,x-p+len]...[x+q-len,x+q-1])

好像是个区间加等差数列,随便前缀和维护一下。

具体地,例如[p,q]加1...q-p+1,这种事情我们用两个数组s1,s2来维护,s1[p...q]+=1,s2[p...q]-=p-1,这个前缀和搞搞。最后我们只要统计s1*i+s2就行了。

实现时l和r需要一边开一边闭(一边大于,一边大于等于),然后用单调栈维护即可。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. ll MOD=;
  5. #define SZ 2333333
  6. int n; ll hh[SZ];
  7. #define gc getchar()
  8. int gi_()
  9. {
  10. int s,c;
  11. while(c=gc,c<||c>);
  12. s=c-;
  13. while(c=gc,c>=&&c<=) s=s*+c-;
  14. return s;
  15. }
  16. #define gi gi_()
  17. int L[SZ],R[SZ],ss[SZ],sn=;
  18. ll q1[SZ],q2[SZ];
  19. void add(ll& a,ll b)
  20. {
  21. a+=b; a%=MOD;
  22. if(a<) a+=MOD;
  23. }
  24. int main()
  25. {
  26. n=gi;
  27. for(int i=;i<=n;i++) hh[i]=gi;
  28. for(int i=;i<=n;i++)
  29. {
  30. while(sn&&hh[ss[sn]]<hh[i]) --sn;
  31. if(sn) L[i]=ss[sn]; ss[++sn]=i;
  32. }
  33. sn=;
  34. for(int i=n;i>=;i--)
  35. {
  36. while(sn&&hh[ss[sn]]<=hh[i]) --sn;
  37. if(sn) R[i]=ss[sn]; else R[i]=n+;
  38. ss[++sn]=i;
  39. }
  40. for(int i=;i<=n;i++) hh[i]%=MOD;
  41. for(int i=;i<=n;i++)
  42. {
  43. int l=L[i],r=R[i];
  44. //1,min(i-l,r-i),max(i-l,r-i),(r-l)
  45. add(q1[],hh[i]); add(q1[min(i-l,r-i)],-hh[i]);
  46. add(q2[min(i-l,r-i)],min(i-l,r-i)*(ll)hh[i]%MOD);
  47. add(q2[max(i-l,r-i)],(r-l)*(ll)hh[i]%MOD-min(i-l,r-i)*(ll)hh[i]%MOD);
  48. add(q2[r-l],-(r-l)*(ll)hh[i]%MOD);
  49. add(q1[max(i-l,r-i)],-hh[i]); add(q1[r-l],hh[i]);
  50. }
  51. int ans=;
  52. for(int i=;i<=n;i++)
  53. {
  54. add(q1[i],q1[i-]); add(q2[i],q2[i-]);
  55. ll orz=((q1[i]*i%MOD+q2[i]%MOD)%MOD+MOD)%MOD;
  56. ans^=orz;
  57. }
  58. printf("%d\n",ans);
  59. }

C. 果冻运输

好好的一道人类智慧提答(确实很好玩)硬生生搞成了暴搜题...

开始我写了个暴力,看看数据范围,心想:肯定搜不出来,就只写了个iddfs,然后把状态hash一下输出,目测找一找规律...

最后有几个点目测玩到了一些两三分的acceptable answer...其他点都搜出1分左右...旁边wwf大爷玩了5h提答,看起来过了十几个点,结果交上去都是两三分,结果总分还没我一堆1分高...惨啊

Q:没想到A*吗?

A:想啦,感觉估价函数非常蛋疼...谁知道设成同色联通块个数这种辣鸡玩意儿就行了...

Q:那也比傻逼暴搜好啊

A:惨啊

人类智慧做法可戳:http://dram.blog.uoj.ac/blog/1864(当然不是我写的

A*大法可戳:http://immortalco.blog.uoj.ac/blog/1854

有空去写写把...

A. Jakarta Skyscrapers

大意就是有一个集合,里面可以容纳正整数。开始里面只有a和b两个正整数,对于集合中两个数x和y,可以通过一次操作得到x-y并插入到集合中。(注意到集合中只能有正整数,所以必须x>=y)。求一些操作使得集合中包含正整数c。输出任意一种步数小于400的方案,如果不存在输出-1。

显然400步内不存在,那么肯定也不存在解了...

然后我们写个暴力,可以发现,A>=B时当且仅当C<=A且gcd(A,B)|C才有解,所以我们就可以判出-1。

(以下内容与题解一点关系都没有)

然后我们发现gcd不是这么写吗:

  1. ll gcd(ll a,ll b)
  2. {
  3. while(b)
  4. {
  5. ll t=a%b; a=b; b=t;
  6. }
  7. return a;
  8. }

那么假如我们自己实现了什么方法,能高效地在这个系统中实现取模和乘法,那么我们就这样做gcd,最后乘上C/gcd(A,B)就做完了。

接下来我们就说说怎么做吧。

减法:有啦 1次

加法:注意到A-(A-x-y)=x+y。 3次

乘法:注意到我们可以快速加 O(log)次

取模:被除数-商*除数 O(log)次

那么gcd的复杂度:

复杂度似乎挺科学?可是我这样写完只有70...看到一个点403次简直哭瞎。

后面用个map加了点记忆化就行啦。求hack

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <map>
  5. using namespace std;
  6. typedef long long ll;
  7. #define SZ 666666
  8. ll A,B,C,la[SZ],lb[SZ];
  9. int ls=;
  10. map<ll,bool> qd;
  11. //O(1)
  12. ll gminus(ll a,ll b)
  13. {
  14. if(!b) return a;
  15. if(a==b) return ;
  16. if(qd[a-b]) return a-b;
  17. qd[a-b]=;
  18. ++ls; la[ls]=a; lb[ls]=b;
  19. return a-b;
  20. }
  21. //O(3)
  22. ll gadd(ll a,ll b)
  23. {
  24. if(a+b>=A) return A;
  25. if(qd[a+b]) return a+b;
  26. gminus(A,a);
  27. gminus(A-a,b);
  28. gminus(A,A-a-b);
  29. return a+b;
  30. }
  31. ll ss[];
  32. //O(log)
  33. //不需要b在集合中
  34. ll gmul(ll a,ll b)
  35. {
  36. if(qd[a*b]) return a*b;
  37. ll tg=a*b;
  38. ll cur=A,sn=;
  39. while(b)
  40. {
  41. if(b&)
  42. {
  43. for(int i=;i<=sn;i++) gadd(ss[i],ss[i]); sn=;
  44. cur=gminus(cur,a);
  45. if(qd[tg-(A-cur)]) return gadd(tg-(A-cur),gminus(A,cur));
  46. }
  47. ss[++sn]=a; a<<=; b>>=;
  48. }
  49. return gminus(A,cur);
  50. }
  51. //O(log)
  52. ll gmod(ll a,ll b)
  53. {
  54. if(a%b==) return ;
  55. if(qd[a%b]) return a%b;
  56. return gminus(a,gmul(b,a/b));
  57. }
  58. ll gcd(ll a,ll b)
  59. {
  60. while(b)
  61. {
  62. ll t=a%b; a=b; b=t;
  63. }
  64. return a;
  65. }
  66. void ggcd(ll a,ll b)
  67. {
  68. while(b)
  69. {
  70. ll t=gmod(a,b); a=b; b=t;
  71. }
  72. }
  73. int main()
  74. {
  75. cin>>A>>B>>C; qd[A]=qd[B]=;
  76. if(A<B) swap(A,B);
  77. if(C%gcd(A,B)!=||C>A) {puts("-1"); return ;}
  78. ll gcdd=gcd(A,B);
  79. ggcd(A,B);
  80. gmul(gcdd,C/gcdd);
  81. cout<<ls<<"\n";
  82. for(int i=;i<=ls;i++) cout<<la[i]<<" "<<lb[i]<<"\n";
  83. }

C. 火车管理

建议不要用题解的做法,高级做法参见 http://wangyisong1996.blog.uoj.ac/blog/1866 (人傻看不懂官方题解

感觉说的十分清楚啊(虽然我也看不懂复杂度分析

两个傻逼错误一个调了一小时,一个调了两小时...大概就是标记到了叶子还往下pushdown标记就失踪了...

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include <stdlib.h>
  7. #include <string>
  8. #include <vector>
  9. #include <set>
  10. #include <map>
  11. #include <queue>
  12. #include <algorithm>
  13. #include <sstream>
  14. #include <stack>
  15. #include <iomanip>
  16. using namespace std;
  17. #define pb push_back
  18. #define inf 1001001001
  19. #define infll 1001001001001001001LL
  20. #define FOR0(i,n) for(int (i)=0;(i)<(n);++(i))
  21. #define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i))
  22. #define mp make_pair
  23. #define pii pair<int,int>
  24. #define ll long long
  25. #define ld double
  26. #define vi vector<int>
  27. #define fi first
  28. #define se second
  29. #define SZ 1048588
  30. #define S2 SZ*65
  31. int an=,lc1[S2],rc1[S2],vs[S2];
  32. int newn(int x) {return vs[++an]=x, an;}
  33. int join(int a,int b)
  34. {
  35. //cout<<"JOIN"<<a<<","<<b<<"\n";
  36. if(a&&b);else return a^b;
  37. int s=newn(vs[a]);
  38. lc1[s]=a; rc1[s]=b;
  39. return s;
  40. }
  41. int delf(int x)
  42. {
  43. if(!x||!lc1[x]) return ;
  44. else if(lc1[lc1[x]])
  45. {
  46. int g=++an;
  47. lc1[g]=delf(lc1[x]);
  48. rc1[g]=rc1[x];
  49. vs[g]=vs[lc1[g]];
  50. return g;
  51. }
  52. else return rc1[x];
  53. }
  54. int ls[SZ],rs[SZ],sum[SZ],tag[SZ],M=,M2=M+M;
  55. void tagit(int x,int vid)
  56. {
  57. if(!x||x>M2) return;
  58. sum[x]=(rs[x]-ls[x]+)*vs[vid];
  59. tag[x]=join(vid,tag[x]); //md这一句调了我一个小时
  60. }
  61. void pd(int x)
  62. {
  63. if(!x||x>M2||!tag[x]||x+x>M2/*wtf*/) return;
  64. tagit(x+x,tag[x]);
  65. tagit(x+x+,tag[x]);
  66. tag[x]=;
  67. }
  68. void upd(int x)
  69. {
  70. //pd(x+x); pd(x+x+1);
  71. sum[x]=sum[x+x]+sum[x+x+];
  72. }
  73. void popt(int x)
  74. {
  75. if(!x||x>M2||!tag[x]) return;
  76. sum[x]-=vs[tag[x]];
  77. tag[x]=delf(tag[x]);
  78. if(tag[x]) sum[x]+=vs[tag[x]];
  79. }
  80. void build()
  81. {
  82. for(int i=;i<=M;i++) ls[i+M]=rs[i+M]=i;
  83. for(int i=M-;i>=;i--) ls[i]=ls[i+i], rs[i]=rs[i+i+];
  84. }
  85. void push(int x,int l,int r,int ns)
  86. {
  87. if(l>r||!x||x>M2) return;
  88. if(ls[x]==l&&rs[x]==r) {tagit(x,ns); return;}
  89. pd(x);
  90. int m=ls[x]+rs[x]>>;
  91. push(x+x,l,min(r,m),ns);
  92. push(x+x+,max(m+,l),r,ns);
  93. upd(x);
  94. }
  95. void pop(int x,int p)
  96. {
  97. if(!x||x>M2||p<ls[x]||p>rs[x]) return;
  98. if(ls[x]==rs[x]) {popt(x); return;}
  99. pd(x); pop(x+x,p); pop(x+x+,p); upd(x);
  100. }
  101. int query(int x,int l,int r)
  102. {
  103. if(l>r||!x||x>M2) return ;
  104. if(ls[x]==l&&rs[x]==r) return sum[x];
  105. pd(x);
  106. int m=ls[x]+rs[x]>>,ans=;
  107. ans+=query(x+x,l,min(r,m));
  108. ans+=query(x+x+,max(m+,l),r);
  109. upd(x);
  110. return ans;
  111. }
  112. int main()
  113. {
  114. build();
  115. int n,m,ty,lans=;
  116. scanf("%d%d%d",&n,&m,&ty);
  117. while(m--)
  118. {
  119. int tp,a,b,c;
  120. scanf("%d",&tp);
  121. if(tp!=)
  122. {
  123. scanf("%d%d",&a,&b);
  124. a=(a+lans*ty)%n+; b=(b+lans*ty)%n+;
  125. if(a>b) swap(a,b);
  126. }
  127. else
  128. {
  129. scanf("%d",&a);
  130. a=(a+lans*ty)%n+;
  131. }
  132. if(tp==) printf("%d\n",lans=query(,a,b));
  133. else if(tp==) pop(,a);
  134. else scanf("%d",&c), push(,a,b,newn(c));
  135. //if(m&127);else cerr<<m<<"\n";
  136. }
  137. }

最后似乎是rank40卡线银牌?反正涨了很多rating还是很高兴的(因为之前rating太低辣)

剩下的题解等看懂了再来补...

UNR #1 题解的更多相关文章

  1. #386. 【UNR #3】鸽子固定器

    #386. [UNR #3]鸽子固定器 题目链接 官方题解 分析: 神奇的做法+链表. 首先按照大小排序. 对于小于选择小于m个物品的时候,这个m个物品一定是一段连续的区间.因为,如果中间空着一个物品 ...

  2. 【UOJ#310】【UNR#2】黎明前的巧克力(FWT)

    [UOJ#310][UNR#2]黎明前的巧克力(FWT) 题面 UOJ 题解 把问题转化一下,变成有多少个异或和为\(0\)的集合,然后这个集合任意拆分就是答案,所以对于一个大小为\(s\)的集合,其 ...

  3. 【UOJ#308】【UNR#2】UOJ拯救计划

    [UOJ#308][UNR#2]UOJ拯救计划 题面 UOJ 题解 如果模数很奇怪,我们可以插值一下,设\(f[i]\)表示用了\(i\)种颜色的方案数. 然而模\(6\)这个东西很有意思,\(6=2 ...

  4. 【UOJ#390】【UNR#3】百鸽笼(动态规划,容斥)

    [UOJ#390][UNR#3]百鸽笼(动态规划,容斥) 题面 UOJ 题解 发现这就是题解里说的:"火山喷发概率问题"(大雾 考虑如果是暴力的话,你需要记录下当前每一个位置的鸽笼 ...

  5. 【UOJ#389】【UNR#3】白鸽(欧拉回路,费用流)

    [UOJ#389][UNR#3]白鸽(欧拉回路,费用流) 题面 UOJ 题解 首先第一问就是判断是否存在一条合法的欧拉回路,这个拿度数和连通性判断一下就行了. 第二问判断转的圈数,显然我们只需要考虑顺 ...

  6. 【UOJ#388】【UNR#3】配对树(线段树,dsu on tree)

    [UOJ#388][UNR#3]配对树(线段树,dsu on tree) 题面 UOJ 题解 考虑一个固定区间怎么计算答案,把这些点搞下来建树,然后\(dp\),不难发现一个点如果子树内能够匹配的话就 ...

  7. 【UOJ#386】【UNR#3】鸽子固定器(贪心)

    [UOJ#386][UNR#3]鸽子固定器(贪心) 题面 UOJ 题解 一个不难想到的暴力做法是把东西按照\(s\)排序,这样子我们枚举极大值和极小值,那么我们选择的一定是这一段之间\(v\)最大的那 ...

  8. Educational Round 64 题解

    前言: 这场太难了……我一个紫名只打出两题……(虽说感觉的确发挥不够好) 一群蓝绿名的dalao好像只打了两题都能升分的样子…… 庆幸的是最后A出锅然后unr了>///< 写一波题解纪念这 ...

  9. 「UNR#1」奇怪的线段树

    「UNR#1」奇怪的线段树 一道好题,感觉解法非常自然. 首先我们只需要考虑一次染色最下面被包含的那些区间,因为把无解判掉以后只要染了一个节点,它的祖先也一定被染了.然后发现一次染色最下面的那些区间一 ...

随机推荐

  1. Facebook开源动画库 POP-POPBasicAnimation运用

    动画在APP开发过程中还是经常出现,将花几天的时间对Facebook开源动画库 POP进行简单的学习:本文主要针对的是POPBasicAnimation运用:实例源代码已经上传至gitHub,地址:h ...

  2. objective-c系列-NSMutableString

    ********************************************** NSMutableString为NSString的子类,除了父类的方法,NSMutableStirng还有 ...

  3. iOS 从应用中跳转至系统设置页面里的多种设置页面

    我们在开发app过程中很多时候会需要设置系统权限,这时就需要在应用中跳转至系统设置页面权限设置页面,以下是自己结合网上的资料总结的一些经验: 直接从应用中跳转至系统设置中这个应用的权限设置页面 NSU ...

  4. DB2LOOK命令提取数据库对象信息

    提取复制数据库的DDL语句:db2look -d BCDLJS -e -o db2look.sql -a -a:导出所有用户的DDL-o: 定向结果到文件-d: 数据库名-e: 抽取复制数据库所需的 ...

  5. C#生成注册码

    string t = DateTime.Now.Ticks.ToString(); t = DESKey.DESEncrypt(t, DESKey.DesKeyStr); string[] strid ...

  6. win7+iis7.5+asp.net下 CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 解决方案

    http://www.cnblogs.com/finesite/archive/2011/01/28/1946940.html 给C:\Windows\temp 文件夹赋予完全控制权限,如图:

  7. Percona XtraBackup User Manual 阅读笔记

    XtraBackup XtraBackup 2 安装XtraBackup 2.1 安装XtraBackup binary版本 2.1.1 yum的安装方法: 2.1.2 直接下载rpm包安装 3 Xt ...

  8. EF深入系列--细节

    1.在调试的时候,查看EF生成的SQL语句 在Context类的构造函数中添加以下代码,就可以在调试的时候在[输出]窗口中看到SQL语句 this.Database.Log = s => Sys ...

  9. 多年前写的DataTable与实体类的转换,已放github

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 阅读目录 介绍 起因 代码 UnitTest G ...

  10. Linux磁盘管理之逻辑结构主引导扇区02

    一.主引导扇区 主引导扇区位于硬盘的0磁道0柱面1扇区,共占用了63个扇区,但实际上只使用了512字节,由三大部分组成: 1.主引导记录MBR(Master Boot Record):占446字节. ...