zoukankan      html  css  js  c++  java
  • 2013多校训练赛第二场 总结

      昨天打多校的第二场,状态还算可以,不会像第一场那样浑浑噩噩的敲过去了。可是这次的排名却比第一次要低了。

      其实昨天比赛很不顺,主要是机房的机器不够,导致我们开局一小时后从三台机减少到只剩一台机。

      开始的时候,队友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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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 }
    View Code

      总的来说,我在比赛中打了一场酱油,做了两道水题。实际上还有几题是可以做的,例如4613,这题开始的时候就想到可以把给定的点转化成一个数列,可惜想不到怎么确定以哪个点为中心。其实这题能找到中心,搞一个KMP就可以的了。

    UPD: 

    Problem - 4613

      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 }
    View Code

      题解说用KMP,不过觉得没有这样的必要,我们要的是确定一个序列的起始位置,所以我用了最小表示法来过这题。

    ——written by Lyon

  • 相关阅读:
    Building Forest CodeForces
    欢迎使用CSDN-markdown编辑器
    Travelling HDU
    Card Collector HDU
    Doing Homework HDU
    Mirror Number SPOJ
    Palindromic Numbers LightOJ
    Magic Numbers CodeForces
    Xor-sequences CodeForces
    Little Elephant and Elections CodeForces
  • 原文地址:https://www.cnblogs.com/LyonLys/p/2013_07_25_Lyon.html
Copyright © 2011-2022 走看看