昨天打多校的第二场,状态还算可以,不会像第一场那样浑浑噩噩的敲过去了。可是这次的排名却比第一次要低了。
其实昨天比赛很不顺,主要是机房的机器不够,导致我们开局一小时后从三台机减少到只剩一台机。
开始的时候,队友ly像开挂一样,瞬间就看懂了1002,20min敲出了代码,抢了个fb。然后就是1009,这题其实很简单,很容易可以看出就是一个二分匹配的题。题目大意是,给出一些1*2的方块,有横向和纵向放置两种,其中只可能出现横向跟纵向重叠的情况,不会横向和横向纵向和纵向重叠。要求求出,最多可以剩下多少方块,是的它们之间两两不重叠。这样子,就可以对有重叠部分的横向和纵向方块添加一条边。然后求出最大匹配,就是最少要删除的方块数目。最后的答案是n+m减去匹配的数目。
然后就是队友卡1006了,这时,为了打破窘境(2个小时才做了2题),我去看了一下1007,好水的一道三维几何的题。这题的题意是给出一些空间圆柱,要求求出所有圆柱之间的最短距离。如果有重叠的部分,就输出Lucky。其实可以直接将圆柱看成直线,然后求出空间直线的最短距离即可。1y。
在我过了1007以后,队友xdp也接着出了1001。最后整场比赛就就卡在1006了。在不停的给1006出数据以后,最终过了1006,然后才看到1004是简单的线段树,这时的时间已经剩下一个钟不够,最后以5题结束了比赛,线段树没有及时写出来。
这次的组队,主要欠缺在于明明已知09是二分,结果搞了很久贪心wa了几次。
组队的时候如果看出算法,就应该直接上那个模板,而不应该想虽然敲的简单,却不能肯定对的做法。
贴一下代码:
hdu 4619:(二分匹配的题,用了HK算法,不过因为边数比较少,可以直接用匈牙利算法。)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 #include <vector> 8 9 using namespace std; 10 const int N = 1111; 11 vector<int> rel[N]; 12 13 bool overlap(int a, int b, int c, int d) { 14 if (c == a && d + 1 == b) return true; 15 if (c == a && d == b) return true; 16 if (c == a + 1 && d + 1 == b) return true; 17 if (c == a + 1 && d == b) return true; 18 return false; 19 } 20 21 int mx[N], my[N], rx[N], ry[N]; 22 int hx[N], hy[N], vx[N], vy[N]; 23 queue<int> Q; 24 25 bool HKbfs(int n) { 26 bool ret = false; 27 while (!Q.empty()) Q.pop(); 28 memset(rx, 0, sizeof(rx)); 29 memset(ry, 0, sizeof(ry)); 30 for (int i = 0; i < n; i++) { 31 if (mx[i] == -1) Q.push(i); 32 } 33 while (!Q.empty()) { 34 int cur = Q.front(); 35 Q.pop(); 36 for (int i = 0; i < rel[cur].size(); i++) { 37 int t = rel[cur][i]; 38 if (!ry[t]) { 39 ry[t] = rx[cur] + 1; 40 if (~my[t]) { 41 rx[my[t]] = ry[t] + 1; 42 Q.push(my[t]); 43 } else { 44 ret = true; 45 } 46 } 47 } 48 } 49 return ret; 50 } 51 52 bool HKdfs(int cur) { 53 for (int i = 0; i < rel[cur].size(); i++) { 54 int t = rel[cur][i]; 55 if (ry[t] == rx[cur] + 1) { 56 ry[t] = 0; 57 if (my[t] == -1 || HKdfs(my[t])) { 58 my[t] = cur; 59 mx[cur] = t; 60 return true; 61 } 62 } 63 } 64 return false; 65 } 66 67 int HK(int n) { 68 int cnt = 0; 69 memset(mx, -1, sizeof(mx)); 70 memset(my, -1, sizeof(my)); 71 while (HKbfs(n)) { 72 for (int i = 0; i < n; i++) if (mx[i] == -1 && HKdfs(i)) cnt++; 73 } 74 return cnt; 75 } 76 77 int main() { 78 int n, m; 79 while (cin >> n >> m && (n || m)) { 80 for (int i = 0; i < n; i++) cin >> hx[i] >> hy[i]; 81 for (int i = 0; i < m; i++) cin >> vx[i] >> vy[i]; 82 for (int i = 0; i < n; i++) { 83 rel[i].clear(); 84 for (int j = 0; j < m; j++) { 85 if (overlap(hx[i], hy[i], vx[j], vy[j])) { 86 //cout << i << ' ' << j << endl; 87 rel[i].push_back(j); 88 } 89 } 90 } 91 cout << n + m - HK(n) << endl; 92 } 93 return 0; 94 }
hdu 4617:(三维几何)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 #include <vector> 8 9 using namespace std; 10 11 const double EPS = 1e-8; 12 const int N = 33; 13 inline int sgn(double x) { return (x > EPS) - (x < -EPS);} 14 struct Point { 15 double x, y, z; 16 Point() {} 17 Point(double x, double y, double z) : x(x), y(y), z(z) {} 18 Point operator + (Point a) { return Point(x + a.x, y + a.y, z + a.z);} 19 Point operator - (Point a) { return Point(x - a.x, y - a.y, z - a.z);} 20 Point operator * (double p) { return Point(x * p, y * p, z * p);} 21 Point operator / (double p) { return Point(x / p, y / p, z / p);} 22 } pt[N][3]; 23 24 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y + a.z * b.z;} 25 inline Point cross(Point a, Point b) { return Point(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);} 26 inline double veclen(Point x) { return sqrt(dot(x, x));} 27 inline double ptdis(Point a, Point b) { return veclen(a - b);} 28 inline Point vecunit(Point x) { return x / veclen(x);} 29 30 bool lldis(Point p1, Point u, Point p2, Point v, double &s) { 31 double b = dot(u, u) * dot(v, v) - dot(u, v) * dot(u, v); 32 if (sgn(b) == 0) return false; 33 double a = dot(u, v) * dot(v, p1 - p2) - dot(v, v) * dot(u, p1 - p2); 34 s = a / b; 35 return true; 36 } 37 38 double p2l(Point p, Point a, Point b) { 39 Point v1 = b - a, v2 = p - a; 40 return veclen(cross(v1, v2)) / veclen(v1); 41 } 42 43 Point p[N], nor[N]; 44 double r[N]; 45 46 int main() { 47 int T, n; 48 cin >> T; 49 while (T-- && cin >> n) { 50 for (int i = 0; i < n; i++) { 51 for (int j = 0; j < 3; j++) cin >> pt[i][j].x >> pt[i][j].y >> pt[i][j].z; 52 p[i] = pt[i][0]; 53 r[i] = veclen(pt[i][0] - pt[i][1]); 54 nor[i] = cross(pt[i][1] - pt[i][0], pt[i][2] - pt[i][0]); 55 } 56 double ans = 1e10; 57 bool touch = false; 58 for (int i = 0; i < n && !touch; i++) { 59 for (int j = i + 1; j < n && !touch; j++) { 60 double s, t, dis; 61 if (lldis(p[i], nor[i], p[j], nor[j], s)) { 62 lldis(p[j], nor[j], p[i], nor[i], t); 63 Point a = p[i] + nor[i] * s; 64 Point b = p[j] + nor[j] * t; 65 dis = ptdis(a, b); 66 } else dis = p2l(p[i], p[j], p[j] + nor[j]); 67 //cout << i << ' ' << j << ' ' << dis << endl; 68 if (dis <= r[i] + r[j]) touch = true; 69 ans = min(ans, dis - r[i] - r[j]); 70 } 71 } 72 if (touch) puts("Lucky"); 73 else printf("%.2f ", ans); 74 } 75 return 0; 76 }
hdu 4611:(模拟,队友xdp过的)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 7 #define ll long long 8 9 ll gcd(ll a,ll b){ 10 return b?gcd(b,a%b):a; 11 } 12 ll lcm(ll a,ll b){ 13 return a/gcd(a,b)*b; 14 } 15 ll myabs(ll key){ 16 if(key<0) return -key; 17 return key; 18 } 19 20 int main(){ 21 // freopen("in","r",stdin); 22 int t; 23 cin>>t; 24 while(t--){ 25 ll l=0,r=0,rlcm=0,rsum=0; 26 ll n,a,b; 27 cin>>n>>a>>b; 28 // cout<<n<<endl; 29 if(a<b) swap(a,b); 30 ll c=n%lcm(a,b); 31 do{ 32 // cout<<l<<' '<<r<<endl; 33 ll dif=myabs(l-r); 34 ll Max=min(a-l,b-r); 35 // printf("Max = %lld, dif = %lld ",Max,dif); 36 rlcm+=Max*dif; 37 // printf("rlcm = 38 if(c>=Max){ 39 rsum+=Max*dif; 40 c-=Max; 41 } 42 else{ 43 rsum+=c*dif; 44 c=0; 45 } 46 l+=Max; 47 r+=Max; 48 l%=a; 49 r%=b; 50 // cout<<l<<' '<<r<<endl; 51 }while(l!=0 || r!=0); 52 ll f=n/lcm(a,b); 53 cout<<rlcm*f+rsum<<endl; 54 } 55 return 0; 56 }
hdu 4616:(树dp,队友ly过的)
1 #pragma comment(linker,"/STACK:102400000,102400000") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <queue> 7 #include <cmath> 8 #include <stack> 9 typedef long long LL; 10 11 const int N = 50005; 12 using namespace std; 13 int n,c; 14 LL dp[N][5][5]; 15 int tot,pre[N]; 16 struct edge{ 17 int v,next; 18 }e[N<<1]; 19 LL val[N]; 20 int trap[N]; 21 22 void init(){ 23 tot=0; 24 memset(pre,-1,sizeof(pre)); 25 memset(dp,-1,sizeof(dp)); 26 } 27 28 void add(int u,int v){ 29 edge E={v,pre[u]}; 30 e[tot]=E,pre[u]=tot++; 31 } 32 33 void input(){ 34 scanf("%d%d",&n,&c); 35 int u,v; 36 for(int i=0;i<n;i++){ 37 scanf("%I64d%d",&val[i],&trap[i]); 38 } 39 for(int i=1;i<n;i++){ 40 scanf("%d%d",&u,&v); 41 add(u,v),add(v,u); 42 } 43 } 44 45 void dfs1(int u,int fa){ 46 dp[u][trap[u]][0]=val[u]; 47 for(int i=pre[u];i!=-1;i=e[i].next){ 48 int v=e[i].v; 49 if(v==fa) continue; 50 dfs1(v,u); 51 int lim; 52 if(trap[u]) lim=c; 53 else lim=c-1; 54 for(int j=trap[u];j<=lim;j++){ 55 if(dp[v][j-trap[u]][0]!=-1){ 56 if(dp[u][j][0]<=dp[v][j-trap[u]][0]+val[u]){ 57 // if(u==3&&j==0) printf("!!! dp[%d][%d][0]=%lld ",v,j-trap[u],dp[v][j-trap[u]][0]); 58 dp[u][j][1]=dp[u][j][0]; 59 dp[u][j][0]=dp[v][j-trap[u]][0]+val[u]; 60 } 61 else{ 62 if(dp[u][j][1]<dp[v][j-trap[u]][0]+val[u]){ 63 dp[u][j][1]=dp[v][j-trap[u]][0]+val[u]; 64 } 65 } 66 } 67 } 68 } 69 } 70 71 LL res; 72 73 void dfs2(int u,int fa){ 74 for(int i=0;i<=c;i++){ 75 for(int j=0;j<3;j++){ 76 res=max(res,dp[u][i][j]); 77 } 78 } 79 for(int i=pre[u];i!=-1;i=e[i].next){ 80 int v=e[i].v; 81 if(v==fa) continue; 82 int lim=c-1; 83 for(int j=trap[u];j<=lim;j++){ 84 if(j+trap[v]>c) continue; 85 if(dp[u][j][0]==dp[v][j-trap[u]][0]+val[u]){ 86 if(dp[u][j][1]!=-1) dp[v][j+trap[v]][2]=max(dp[v][j+trap[v]][2],dp[u][j][1]+val[v]); 87 // if(v==7&&j+trap[v]==2) printf("dp[%d][%d][1]=%lld val[%d]=%lld ",u,j,dp[u][j][1],v,val[v]); 88 89 } 90 else if(dp[u][j][0]!=-1){ 91 // if(v==7&&j+trap[v]==2) printf("dp[%d][%d][0]=%lld val[%d]=%lld ",u,j,dp[u][j][0],v,val[v]); 92 dp[v][j+trap[v]][2]=max(dp[v][j+trap[v]][2],dp[u][j][0]+val[v]); 93 } 94 // if(v==7&&j+trap[v]==2) printf("dp[%d][%d][2]=%lld val[%d]=%lld ",u,j,dp[u][j][2],v,val[v]); 95 if(dp[u][j][2]!=-1) dp[v][j+trap[v]][2]=max(dp[v][j+trap[v]][2],dp[u][j][2]+val[v]); 96 } 97 dfs2(v,u); 98 } 99 } 100 101 void get(){ 102 puts("~~~~~~~~~~~~~~~~~~~~~~"); 103 for(int i=3;i<=3;i++){ 104 for(int j=0;j<=c;j++){ 105 for(int k=0;k<3;k++){ 106 if(dp[i][j][k]!=-1) printf("dp[%d][%d][%d]=%lld ",i,j,k,dp[i][j][k]); 107 } 108 } 109 } 110 } 111 112 int main(){ 113 // freopen("in","r",stdin); 114 int T; 115 scanf("%d",&T); 116 while(T--){ 117 init(); 118 input(); 119 res=-1; 120 dfs1(0,-1); 121 dp[0][trap[0]][2]=0; 122 dfs2(0,-1); 123 // get(); 124 cout << res << endl; 125 } 126 return 0; 127 }
hdu 4614:(线段树,跟POJ的hotel那题相似,是比较经典的模型)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 #include <vector> 8 9 using namespace std; 10 11 const int N = 55555; 12 13 #define lson l, m, rt << 1 14 #define rson m + 1, r, rt << 1 | 1 15 #define root 0, n - 1, 1 16 17 int ml[N << 2], mr[N << 2], sum[N << 2], late[N << 2]; 18 int n; 19 20 void up(int rt) { 21 int ls = rt << 1, rs = rt << 1 | 1; 22 sum[rt] = sum[ls] + sum[rs]; 23 if (ml[ls] == -1) ml[rt] = ml[rs]; 24 else ml[rt] = ml[ls]; 25 if (mr[rs] == -1) mr[rt] = mr[ls]; 26 else mr[rt] = mr[rs]; 27 } 28 29 void down(int rt, int l, int r) { 30 int ls = rt << 1, rs = rt << 1 | 1; 31 int len = r - l + 1; 32 int lr = len >> 1, ll = len - lr; 33 if (~late[rt]) { 34 sum[ls] = late[rt] * ll; 35 sum[rs] = late[rt] * lr; 36 if (late[rt]) { 37 ml[ls] = ml[rs] = mr[ls] = mr[rs] = -1; 38 } else { 39 ml[ls] = l, mr[ls] = l + ll - 1; 40 ml[rs] = r - lr + 1, mr[rs] = r; 41 } 42 late[ls] = late[rs] = late[rt]; 43 late[rt] = -1; 44 } 45 } 46 47 void build(int l, int r, int rt) { 48 late[rt] = -1; 49 if (l == r) { 50 ml[rt] = mr[rt] = l; 51 sum[rt] = 0; 52 return ; 53 } 54 int m = l + r >> 1; 55 build(lson); 56 build(rson); 57 up(rt); 58 } 59 60 int clean(int L, int R, int l, int r, int rt) { 61 int ret = 0; 62 if (L <= l && r <= R) { 63 // cout << l << ' ' << r << " sum " << sum[rt] << endl; 64 ret = sum[rt]; 65 late[rt] = 0; 66 sum[rt] = 0; 67 ml[rt] = l, mr[rt] = r; 68 return ret; 69 } 70 int m = l + r >> 1; 71 down(rt, l, r); 72 if (L <= m) ret += clean(L, R, lson); 73 if (m < R) ret += clean(L, R, rson); 74 up(rt); 75 return ret; 76 } 77 78 typedef pair<int, int> PII; 79 PII insert(int L, int R, int l, int r, int rt) { 80 PII ret = PII(-1, -1); 81 if (L <= l && r <= R) { 82 late[rt] = 1; 83 sum[rt] = r - l + 1; 84 ret = PII(ml[rt], mr[rt]); 85 ml[rt] = mr[rt] = -1; 86 return ret; 87 } 88 int m = l + r >> 1; 89 down(rt, l, r); 90 if (L <= m) ret = insert(L, R, lson); 91 if (m < R) { 92 PII tmp = insert(L, R, rson); 93 if (ret.first == -1) ret.first = tmp.first; 94 if (tmp.second != -1) ret.second = tmp.second; 95 } 96 up(rt); 97 return ret; 98 } 99 100 int getsum(int L, int R, int l, int r, int rt) { 101 if (L <= l && r <= R) return r - l + 1 - sum[rt]; 102 down(rt, l, r); 103 int m = l + r >> 1; 104 int sum = 0; 105 if (L <= m) sum += getsum(L, R, lson); 106 if (m < R) sum += getsum(L, R, rson); 107 up(rt); 108 return sum; 109 } 110 111 int dc(int l, int r, int cnt) { 112 int mk = -1, m, p = l; 113 while (l <= r) { 114 m = l + r >> 1; 115 //cout << m << "= =" << getsum(p, m, root) << '~' << cnt << endl; 116 if (getsum(p, m, root) >= cnt) mk = m, r = m - 1; 117 else l = m + 1; 118 } 119 return mk; 120 } 121 122 int main() { 123 int T, m; 124 int op, x, y; 125 PII tmp; 126 cin >> T; 127 while (T-- && cin >> n >> m) { 128 build(root); 129 while (m--) { 130 scanf("%d%d%d", &op, &x, &y); 131 if (op == 1) { 132 int cnt = getsum(x, n - 1, root); 133 y = min(y, cnt); 134 int pos = dc(x, n - 1, y); 135 //cout << x << '=' << pos << endl; 136 if (~pos) { 137 PII tmp = insert(x, pos, root); 138 //cout << tmp.first << '~' << tmp.second << endl; 139 if (~tmp.first) printf("%d %d ", tmp.first, tmp.second); 140 else puts("Can not put any one."); 141 } else { 142 puts("Can not put any one."); 143 } 144 } else { 145 printf("%d ", clean(x, y, root)); 146 } 147 } 148 puts(""); 149 } 150 return 0; 151 }
hdu 4612:(好像是强连通分量吧,图论,队友ly过的)
1 #pragma comment(linker,"/STACK:102400000,102400000") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <queue> 7 #include <cmath> 8 #include <stack> 9 10 const int N = 200005; 11 const int E = 1000005; 12 using namespace std; 13 int n,m; 14 int tot,pre[N]; 15 struct edge{ 16 int u,v,next; 17 }e[E<<1]; 18 int dfn[N],low[N],id[N],st[N]; 19 int scc,num,top; 20 bool vis[N]; 21 22 void init(){ 23 tot=0; 24 memset(pre,-1,sizeof(pre)); 25 } 26 27 void add(int u,int v){ 28 edge E={u,v,pre[u]}; 29 e[tot]=E,pre[u]=tot++; 30 } 31 32 void input(){ 33 int u,v; 34 while(m--){ 35 scanf("%d%d",&u,&v); 36 add(u,v),add(v,u); 37 } 38 } 39 40 void dfs(int u,int fa){ 41 dfn[u]=low[u]=++num; 42 vis[u]=1,st[++top]=u; 43 int flag=1; 44 for(int i=pre[u];i!=-1;i=e[i].next){ 45 int v=e[i].v; 46 if(v==fa&&flag){ 47 flag=0; 48 continue; 49 } 50 if(!dfn[v]){ 51 dfs(v,u); 52 low[u]=min(low[u],low[v]); 53 } 54 else if(vis[v]) low[u]=min(low[u],dfn[v]); 55 } 56 if(low[u]==dfn[u]){ 57 scc++; 58 while(1){ 59 int v=st[top--]; 60 id[v]=scc,vis[v]=0; 61 if(v==u) break; 62 } 63 } 64 } 65 66 void tarjan(){ 67 memset(dfn,0,sizeof(dfn)); 68 memset(vis,0,sizeof(vis)); 69 scc=num=top=0; 70 for(int i=1;i<=n;i++){ 71 if(!dfn[i]) dfs(i,-1); 72 // printf("id[%d]=%d ",i,id[i]); 73 } 74 } 75 76 void build(){ 77 int nn=tot; 78 init(); 79 for(int i=0;i<nn;i++){ 80 int u=e[i].u,v=e[i].v; 81 if(id[u]!=id[v]) add(id[u],id[v]); 82 } 83 } 84 85 int dis[N]; 86 int bfs(int s,int &t){ 87 queue<int> q; 88 memset(vis,0,sizeof(vis)); 89 dis[s]=0,vis[s]=1,t=s; 90 q.push(s); 91 int res=0; 92 while(!q.empty()){ 93 int u=q.front(); 94 q.pop(); 95 if(res<dis[u]){ 96 res=dis[u]; 97 t=u; 98 } 99 for(int i=pre[u];i!=-1;i=e[i].next){ 100 int v=e[i].v; 101 if(!vis[v]){ 102 vis[v]=1; 103 dis[v]=dis[u]+1; 104 q.push(v); 105 } 106 } 107 } 108 return res; 109 } 110 111 int main(){ 112 // freopen("in","r",stdin); 113 while(scanf("%d%d",&n,&m)>0){ 114 if(n==0&&m==0) break; 115 init(); 116 input(); 117 tarjan(); 118 build(); 119 int u,v; 120 int res=bfs(1,u); 121 res=bfs(u,v); 122 printf("%d ",scc-1-res); 123 } 124 return 0; 125 }
总的来说,我在比赛中打了一场酱油,做了两道水题。实际上还有几题是可以做的,例如4613,这题开始的时候就想到可以把给定的点转化成一个数列,可惜想不到怎么确定以哪个点为中心。其实这题能找到中心,搞一个KMP就可以的了。
UPD:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cmath> 5 #include <cstring> 6 7 using namespace std; 8 9 const int N = 33333; 10 const double EPS = 1e-8; 11 const double PI = acos(-1.0); 12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);} 13 struct Point { 14 double x, y; 15 Point() {} 16 Point(double x, double y) : x(x), y(y) {} 17 bool operator < (Point a) const { return sgn(x - a.x) < 0 || sgn(x - a.x) == 0 && y < a.y;} 18 bool operator == (Point a) const { return sgn(x - a.x) == 0 && sgn(y - a.y) == 0;} 19 } tmp[N], str[N], sub[N]; 20 21 template<class T> T sqr(T x) { return x * x;} 22 23 int convert1(Point *s, Point *t, int n, double &u) { 24 double sx = 0, sy = 0; 25 for (int i = 0; i < n; i++) sx += s[i].x, sy += s[i].y; 26 sx /= n, sy /= n; 27 int m = 0; 28 for (int i = 0; i < n; i++) if (sgn(sx - s[i].x) || sgn(sy - s[i].y)) s[m++] = s[i]; 29 //cout << "sx " << sx << " sy " << sy << endl; 30 u = 0; 31 for (int i = 0; i < m; i++) { 32 u = max(u, sqrt(sqr(sx - s[i].x) + sqr(sy - s[i].y))); 33 t[i].x = atan2(s[i].y - sy, s[i].x - sx); 34 } 35 u /= 10000; 36 for (int i = 0; i < m; i++) t[i].y = sqrt(sqr(sx - s[i].x) + sqr(sy - s[i].y)) / u; 37 sort(t, t + m); 38 return m; 39 } 40 41 inline int cmp(Point a, Point b) { return a == b ? 0 : (a < b ? -1 : 1);} 42 43 int minexp(Point *s, int n) { 44 int i = 0, j = 1, k = 0, t; 45 while (i < n && j < n && k < n) { 46 t = cmp(s[(i + k) % n], s[(j + k) % n]); 47 if (!t) k++; 48 else { 49 if (t > 0) i += k + 1; 50 else j += k + 1; 51 if (i == j) j++; 52 k = 0; 53 } 54 } 55 return min(i, j); 56 } 57 58 void reflect(Point *s, int n) { 59 for (int i = 0; i < n; i++) s[i].x = -s[i].x; 60 sort(s, s + n); 61 } 62 63 void convert2(Point *s, Point *t, int n) { 64 s[n] = s[0]; 65 s[n].x += 2 * PI; 66 for (int i = 0; i < n; i++) t[i].x = s[i + 1].x - s[i].x, t[i].y = s[i].y; 67 //for (int i = 0; i < n; i++) cout << "rel " << t[i].x << ' ' << t[i].y << endl; 68 } 69 70 bool check(Point *s, Point *t, int n) { 71 bool ret = true; 72 int pos = minexp(t, n); 73 rotate(t, t + pos, t + n); 74 //for (int i = 0; i < n; i++) cout << t[i].x << '~' << t[i].y << endl; 75 //puts("~~~~!!!!!!!!!!!!!!~~~"); 76 for (int i = 0; i < n && ret; i++) if (!(s[i] == t[i])) ret = false; 77 return ret; 78 } 79 80 int main() { 81 int n, m, k, T; 82 scanf("%d", &T); 83 while (T-- && ~scanf("%d", &n)) { 84 for (int i = 0; i < n; i++) scanf("%lf%lf", &str[i].x, &str[i].y); 85 double r; 86 int nn = convert1(str, tmp, n, r); 87 //cout << nn << endl; 88 convert2(tmp, str, nn); 89 int pos = minexp(str, nn); 90 rotate(str, str + pos, str + nn); 91 //for (int i = 0; i < nn; i++) cout << str[i].x << ' ' << str[i].y << endl; 92 //puts("~~~~~~~~~~~~~~~~~~~~~"); 93 scanf("%d", &m); 94 while (m--) { 95 scanf("%d", &k); 96 for (int i = 0; i < k; i++) scanf("%lf%lf", &sub[i].x, &sub[i].y); 97 if (k != n) puts("No"); 98 else { 99 double rr; 100 int kk = convert1(sub, tmp, k, rr); 101 if (kk != nn) { 102 puts("No"); 103 continue; 104 } 105 convert2(tmp, sub, kk); 106 if (check(str, sub, kk)) puts("Yes"); 107 else { 108 reflect(tmp, kk); 109 convert2(tmp, sub, kk); 110 if (check(str, sub, kk)) puts("Yes"); 111 else puts("No"); 112 } 113 } 114 } 115 puts(""); 116 } 117 return 0; 118 }
题解说用KMP,不过觉得没有这样的必要,我们要的是确定一个序列的起始位置,所以我用了最小表示法来过这题。
——written by Lyon