BZOJ1100: [POI2007]对称轴osi

77 篇文章 0 订阅
15 篇文章 0 订阅

多组数据清空一定要注意…

一眼感觉是计算几何题…然后不会做….
结果居然是字符串题….

如果我们能将一个多边形表示成一个字符串的话,对称就变成了回文
我们用边长代表这条边,用两条邻边的叉积代表这个点(因为叉积就是有向面积)
然后将这个数字序列复制一份到后面
找所有长度>2*n的回文串
最后答案要/2,因为每个对称轴会被算两次

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 410000;

int n,m;
ll xi[maxn],yi[maxn];

ll sqr(const ll x){return x*x;}
ll cal(const int x)
{
    int y=x-1; if(!y) y=n;
    return sqr(xi[x]-xi[y])+sqr(yi[x]-yi[y]);
}
ll cal2(const int x)
{
    int y=x+1,z=x-1; if(y>n) y=1; if(!z) z=n;
    ll x1=xi[x]-xi[z],y1=yi[x]-yi[z];
    ll x2=xi[y]-xi[z],y2=yi[y]-yi[z];
    return x1*y2-x2*y1;
}

ll s[maxn];
int r[maxn],id,mx;

int main()
{
    int tcase; scanf("%d",&tcase);
    while(tcase--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lld%lld",&xi[i],&yi[i]);
        int len=0; s[0]=LLONG_MAX;
        for(int i=1;i<=n;i++)
            s[++len]=cal(i),s[++len]=cal2(i);
        for(int i=1;i<=len;i++) s[len+i]=s[i];
        len<<=1;
        s[++len]=LLONG_MIN;

        int ans=0; id=mx=0;
        for(int i=1;i<len;i++)
        {
            r[i]=0;
            if(mx>i) r[i]=min(mx-i,r[2*id-i]);
            while(s[i+r[i]]==s[i-r[i]]) r[i]++;
            if(i+r[i]>mx) mx=i+r[i],id=i;
            if(r[i]>n) ans++;
        }
        printf("%d\n",ans>>1);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值