【除草】【hnoi】精简题解
好久没写了。到目前为止也算是刷完了hnoi07-12的题,精简题解第三弹(大多数代码好像都没存就不贴了)
2007:07年的题目略奇葩,刚开始做就被虐爆了啊>_<
海盗分宝
题意不明觉厉。。。
最小矩形覆盖
裸的凸包+旋转卡壳。第一道正经的计算几何。另外这题精度巨卡,建议对着数据调。有关旋转卡壳当时做过ppt,这就不写了。
代码:
1 #include<stdio.h> 2 #include<math.h> 3 #include<iostream> 4 #include<algorithm> 5 #include <cmath> 6 7 #define DEBUG 8 9 10 #define INF (99999.0) 11 #define MAXN (50000+10) 12 #define Next(p) ((p+1)%n) 13 using namespace std; 14 #define EPS 1e-4 15 struct point { 16 double x,y; 17 point(double a,double b) {x=a;y=b;} 18 point(){} 19 }; 20 typedef struct point point; 21 typedef struct point vector; 22 vector xx=point(1,0),yy=point(0,1); 23 bool cmp(point a,point b){ 24 if (a.x==b.x) return a.y<b.y; 25 return a.x<b.x; 26 } 27 bool cmp2(point a,point b){ 28 if (a.y==b.y) return a.x<b.x; 29 return a.y<b.y; 30 } 31 bool cmp3(point a,point b){ 32 if (a.x==b.x) return a.y>b.y; 33 return a.x<b.x; 34 } 35 vector operator + (vector A,vector B) { 36 return vector(A.x+B.x,A.y+B.y); 37 } 38 vector operator - (vector A,vector B) { 39 return vector(A.x-B.x,A.y-B.y); 40 } 41 vector operator * (double k,vector A) { 42 return vector(A.x*k,A.y*k); 43 } 44 double Dot(vector A,vector B) { 45 return A.x*B.x+A.y*B.y; 46 } 47 double Cross(vector A,vector B) { 48 return A.x*B.y-B.x*A.y; 49 } 50 double Len(vector A) { 51 return sqrt(Dot(A,A)); 52 } 53 double Angle(vector A,vector B) { 54 return acos(Dot(A,B)/Len(A)/Len(B)); 55 } 56 vector Rotate(vector A,double rad) { 57 return vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); 58 } 59 int ConvexHull(point *p,int n,point *ch) { 60 int i; 61 sort(p,p+n,cmp); 62 int m=0; 63 for (i=0; i<n; i++) { 64 while (m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--; 65 ch[m++]=p[i]; 66 } 67 int k=m; 68 for (i=n-2; i>=0; i--) { 69 while (m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--; 70 ch[m++]=p[i]; 71 } 72 if (n>1) m--; 73 return m; 74 } 75 double Rotating_Calipers(point *p,int n,point &A,point &B){//double p; 76 int i; 77 double D=-INF; 78 int a,b;//a,b is point of A & B; 79 A=B=p[0]; 80 for (i=0;i<n;i++){ 81 if (p[i].y>A.y) {A=p[i];a=i;} 82 if (p[i].y<B.y) {B=p[i];b=i;} 83 } 84 for (int KK=0;KK<=n;KK++){ 85 double thta1=fabs(Angle(p[Next(a)]-p[a],xx)); 86 double thta2=fabs(Angle(p[Next(b)]-p[b],xx)); 87 if (thta1<thta2){ 88 if (Len(p[Next(a)]-p[b])>D){ 89 D=Len(p[Next(a)]-p[b]); 90 A=p[Next(a)];B=p[b]; 91 } 92 if (Len(p[a]-p[b])>D){ 93 D=Len(p[a]-p[b]); 94 A=p[a];B=p[b]; 95 } 96 a=Next(a); 97 } 98 if (thta1>thta2){ 99 if (Len(p[b]-p[a])>D){ 100 D=Len(p[b]-p[a]); 101 A=p[b];B=p[a]; 102 } 103 if (Len(p[Next(b)]-p[a])>D){ 104 D=Len(p[Next(b)]-p[a]); 105 A=p[Next(b)];B=p[a]; 106 } 107 b=Next(b); 108 } 109 if (thta1==thta2){ 110 if (Len(p[a]-p[b])>D){ 111 D=Len(p[a]-p[b]); 112 A=p[a];B=p[b]; 113 } 114 if (Len(p[Next(a)]-p[b])>D){ 115 D=Len(p[Next(a)]-p[b]); 116 A=p[Next(a)];B=p[b]; 117 } 118 if (Len(p[a]-p[Next(b)])>D){ 119 D=Len(p[a]-p[Next(b)]); 120 A=p[a];B=p[Next(b)]; 121 } 122 if (Len(p[Next(a)]-p[Next(b)])>D){ 123 D=Len(p[Next(a)]-p[Next(b)]); 124 A=p[Next(a)];B=p[Next(b)]; 125 } 126 a=Next(a); 127 b=Next(b); 128 } 129 } 130 return D; 131 } 132 int main() { 133 int n; 134 scanf("%d",&n); 135 point p[MAXN]; 136 for(int i=0; i<n; i++) { 137 scanf("%lf%lf",&p[i].x,&p[i].y); 138 } 139 point ch[MAXN],A,B; 140 int ct=ConvexHull(p,n,ch); 141 142 #ifdef DEBUG_1 143 for (int i=0;i<ct;i++){ 144 cout<<p[i].x<<" "<<p[i].y<<endl; 145 } 146 cout<<ct<<endl; 147 #endif // DEBUG 148 149 150 double D=Rotating_Calipers(ch,ct,A,B); 151 152 double S=D*D*0.5; 153 154 155 int bib=(int)S; 156 if (fabs(bib-S)>EPS) S=bib+1; 157 else S=bib; 158 printf("%.5lf\n",S); 159 160 point middle=0.5*(A+B); 161 vector ttt=middle-A; 162 vector ta,tb; 163 ta=point(-ttt.y,ttt.x); 164 tb=point(ttt.y,-ttt.x); 165 point c,d; 166 c=ta+middle; 167 d=tb+middle; 168 169 point last[10]; 170 last[0]=A;last[1]=B;last[2]=c;last[3]=d; 171 for (int i=0;i<=3;i++){ 172 int fx=(int)last[i].x; 173 int fy=(int)last[i].y; 174 if (fabs(fx-last[i].x)>EPS) last[i].x=fx+1; 175 else last[i].x=fx; 176 if (fabs(fy-last[i].y)>EPS) last[i].y=fy+1; 177 else last[i].y=fy; 178 } 179 180 sort(last,last+4,cmp2); 181 printf("%.5lf %.5lf\n",last[0].x,last[0].y); 182 183 sort(last+1,last+4,cmp3); 184 printf("%.5lf %.5lf\n",last[3].x,last[3].y); 185 printf("%.5lf %.5lf\n",last[2].x,last[2].y); 186 printf("%.5lf %.5lf\n",last[1].x,last[1].y); 187 188 //find the other two point; 189 return 0; 190 }
胜负一子
又不明觉厉了囧。。
神奇游乐园
裸的插头DP。话说当时还没有陈丹琦的论文呢
分裂游戏
这是一个叫什么什么博弈的东西,反正是经典博弈。
思路很巧妙,把每个石子看成是一个独立游戏就可以SG了。
紧急疏散
好题。一看就是网络流构图,但重点是流量上限应该是动态增加的。处理方法和正常的网络流一样。
梦幻岛的宝石
背包DP,对二进制位进行DP。jwc写了一个神奇的分层DP。。我的DP还是弱啊。
所罗门的咒语
不明觉厉第三弹。。Orz clj
2008:08年的题比07强,但是有很多以前没学过的东西
可见直线
继续裸的计算几何。半平面交,注意边界直线一定要取的非常远。
明明的烦恼
prufer编码。这个还没太理解。
越狱
捉鸡的组合计数。不说了
神奇的国度
弦图的贪心染色。可以看cdq的论文,或者组合数学上也有讲
GT考试
kmp+矩阵
洗牌
Burnside引理+DP。又跪在DP上了
玩具装箱
以前写过详细的斜率优化。现在感觉用动态凸包的思想比较好理解。好像是数据水了,乱搞也能过
遥远行星
利用精度乱搞?给神题跪了
2009:09年的题还可以吧
梦幻布丁
链表+启发式合并。以前也写过。看这里
通往城堡之路
科♂学的调整。利用贪心思想确定初始解后进行调整
有趣的数列
打个表发现是Catalan数。
最小圈
二分答案改边权a[i]-b[i]*ans,判负环即可
2010:这周去ACM了,所以题是选着做的。(然后ACM被虐爆了T_T)
合唱队
这就是DP啦
平面图判定
环内和环外对应二分图的两侧,匹配或者2-SAT
物品调度
知道了序列就是是贪心,关键在于求序列。看了题解,用双端链表维护,按GCD分类讨论。
公交线路
压缩状态。没做
取石子游戏
贪心。当时没做
城市建设
动态最小生成树,离线搞。论文题
弹飞绵羊
动态树或者LCT,都太麻烦。。
直接分块,块状数组O(n*sqrt(n))
矩阵
搜索优化?也没做
2011:难度上升,但还是可做的
数学作业
矩阵加速递推。直接用矩阵表示不了,按位分别搞
勾股定理
不明觉厉*4。。看看了看题解觉得好神啊。。。
赛车游戏
贪心。利用柯西不等式可证明
括号修复
splay维护序列,和05年noi那道题一样。暴力30分,感觉可以分块?
任务调度
太神了!模拟退火!RP-完全问题!
XOR路径和
计算对于期望的贡献,然后解方程
数矩形
简单几何
卡农
其实一点也不难,就是想出来也不确定对不对。囧。
2012:最后一年,感觉是做的最好的。
双十字
染色然后记录前缀和,组合计数
与非
按位DP。不太会
排队
简单的排列组合。捆绑,插空,容斥什么的。需要高精度,不想写了然后突然发现BZOJ上可以交python。于是你懂得。
代码:
1 #!/usr/bin/python 2 # Filename: queue.py 3 n,m=raw_input().split() 4 n=int(n) 5 m=int(m) 6 def fac(a): 7 if a==0: 8 return 1 9 ans=1 10 for i in range(1,a+1): 11 ans=ans*i 12 return ans 13 14 def A(a,b): 15 return fac(a)/fac(a-b) 16 17 if n==0: 18 print 0 19 elif m>n+3: 20 print 0 21 else: 22 print A(n,n)*(A(n+1,2)*A(n+3,m)+A(2,2)*A(n+1,1)*A(n+3-1,m-1)*m) 23 exit (0)
矿场搭建
容易发现跟割点有关。于是有两种方法:
删去所有割点后剩下了若干个块,那么答案就是 只与一个割点相连的块数,特殊情况若没有割点答案是2(注意不是1),复杂度O(m)
另一种做法是直接枚举删去的点然后连通分量缩环,取最多的块数即可,复杂度O(n2)
显然这题数据水了,两种方法都能过
三角形覆盖问题
simpson可以搞,据说只有50分?
注意到坐标范围不大,那么可以利用梯形剖分的思想暴力扫描线。每次扫描线+1(注意不用离散,离散了就麻烦了),然后用双端链表维护三角形,开一个数组暴力维护覆盖线段个数。
射箭
首先设方程,因为过原点所以只有两个未知参数a和b。二份答案后列出2*ans个不等式,就变成了裸的半平面交。
我一开始想差分约束了,显然不对。注意差分约束的不等式里没有系数,必须是x1-x2这样的。有系数的只能半平面交
永无乡
显然的启发式合并平衡树
集合选数
做法很神。构造出一个矩阵后就可以状压DP了。网上有很多讲的清楚的题解。