[ZJOI2008]无序运动Movement
Description
D博士对物理有着深入的研究,经典物理、天体物理、量子物理都有着以他的名字命名的定理。最近D博士着迷于研究粒子运动的无规则性。对圣经深信不疑的他相信,上帝创造的任何事物必然是有序的、有理可循的,而不是无规则的、混沌的。 经过长时间的研究,D博士找到了很多出现相当频繁的轨迹片断,他把这些轨迹片断储存在一个很大的数据库内。他需要你帮助他写一个程序,对于一个给出的粒子运动轨迹,统计数据库中每个轨迹片断的出现的次数。 为清楚起见,我们定义一个粒子的轨迹为二维平面上的一个点列(P1, P2, … PN)。点列P的一个子列[i, j]定义为P中一段连续的子序列(Pi, Pi+1, … Pj)。点列P的一个子列[u, v]被称为点列Q = (Q1, Q2 … Qv-u+1)在P中的一次出现,当且仅当Q经过有限次的平移、旋转、翻转、放缩之后得到Q’满足Q’k = Pu+k-1(k =1 … u – v + 1)。 对平面X-Y进行四种操作的解释平移 设平移向量为(dx, dy),则任意点(x,y)平移后的结果为(x+dx, y+dy) 旋转 设旋转角为t,则任意点(x,y)旋转后的结果为 (x cos t – y sin t, x sin t + y cos t)翻转 任意点(x,y) 翻转后的结果为(x, -y) 放缩 设放缩比例为p (p ≠ 0),则任意点(x,y)放缩后的结果为(px,py)
Input
第一行两个整数N、M,分别描述待处理的粒子运动轨迹的点列大小与数据库内的轨迹片断个数。接下来M行依次给出每个轨迹片断。每行先是一个正整数K,表示该轨迹片断点列的长度。然后2K个整数,依次描述点列中的K个点的横坐标与纵坐标。接下来一行2N个整数,依次描述待处理的粒子运动轨迹的点列中N个点的横坐标与纵坐标。
注:输入中的每条轨迹中任意相邻两点不会相同。
Output
应包含M行,依次给出每个片段在待处理运动轨迹中的出现次数。
Sample Input
3 2
2 17 0 10 1
3 0 0 1 0 1 -1
0 0 1 0 1 1
Sample Output
2
1
HINT
N, K ≤ 200 000,片段总长度 ≤ 1600000,输入中给出所有点坐标绝对值均不大于10 000。
考虑能够匹配,两个图形肯定是相似的
所以我们可以直接记录相邻两个边的长度比和夹角
然后炸精度……
换个方式记录,边长可以改为记录相邻两边的边长长度平方最简比(因为都是整点,平方后肯定是整数)
然后角度怎么记?可以用带符号的两边叉积点积最简比记录
翻转的话,把匹配串翻转一下再匹配就好了
注意判断翻转之后是否依然相似
然后AC自动机大力跑,Map存边即可,由于字符集很大,暴力跳Fail即可
/*program from Wolfycz*/
#include<map>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Fi first
#define Se second
#define MK make_pair
#define inf 0x7f7f7f7f
#define sqr(x) ((x)*(x))
#define For(T,i,x) for (T::iterator i=x.begin();i!=x.end();i++)
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int> pii;
typedef unsigned long long ull;
inline char gc(){static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){int x=0,f=1; char ch=gc();for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';return x*f;
}
inline int read(){int x=0,f=1; char ch=getchar();for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';return x*f;
}
inline void print(int x){if (x<0) putchar('-'),x=-x;if (x>9) print(x/10);putchar(x%10+'0');
}
const int N=2e5;
int Ans[N+10];
struct complex{int x,y;complex(int _x=0,int _y=0){x=_x,y=_y;}int operator *(const complex &tis)const{return x*tis.y-y*tis.x;}int operator /(const complex &tis)const{return x*tis.x+y*tis.y;}complex operator +(const complex &tis)const{return complex(x+tis.x,y+tis.y);}complex operator -(const complex &tis)const{return complex(x-tis.x,y-tis.y);}void insert(int _x,int _y){x=_x,y=_y;}
};
struct node{pii scl,rte;//scaling,rotateint gcd(int a,int b){return !b?a:gcd(b,a%b);}pii work(pii tmp){int d=max(1,gcd(abs(tmp.Fi),abs(tmp.Se)));tmp.Fi/=d,tmp.Se/=d;return tmp;}node(pii _scl=MK(0,0),pii _rte=MK(0,0)){scl=work(_scl),rte=work(_rte);}void insert(pii _scl,pii _rte){scl=work(_scl),rte=work(_rte);}bool operator <(const node &tis)const{return scl!=tis.scl?scl<tis.scl:rte<tis.rte;}bool operator ==(const node &tis)const{return scl==tis.scl&&rte==tis.rte;}bool operator !=(const node &tis)const{return !(*this==tis);}
};
struct S1{map<node,int>trie[N+10];int fail[N+10],cnt[N+10],tot,root;vector<int>End[N+10];S1(){tot=root=1;}void insert(node *s,int n,int ID){int p=root;for (int i=1;i<=n;i++){map<node,int>::iterator I=trie[p].find(s[i]);if (I==trie[p].end()) I=trie[p].insert(map<node,int>::value_type(s[i],++tot)).Fi;p=I->Se;}End[p].push_back(ID);}void make_fail(){static int h[N+10];int head=1,tail=1; h[1]=root;for (;head<=tail;head++){int Now=h[head];for (map<node,int>::iterator it=trie[Now].begin();it!=trie[Now].end();it++){int p=fail[Now];while (p&&trie[p].find(it->Fi)==trie[p].end()) p=fail[p];fail[it->Se]=p?trie[p].find(it->Fi)->Se:root;h[++tail]=it->Se;}}}void work(node *s,int len){int p=root;for (int i=1;i<=len;i++){while (p&&trie[p].find(s[i])==trie[p].end()) p=fail[p];p=p?trie[p].find(s[i])->Se:root;for (int x=p;x;x=fail[x]) cnt[x]++;}}void updata(){for (int i=1;i<=tot;i++)For(vector<int>,I,End[i])Ans[*I]+=cnt[i];}
}AC;//Aho-Corasick automaton
int dis(pii x,pii y){return sqr(x.Fi-y.Fi)+sqr(x.Se-y.Se);}
int A[2][N+10],Len[N+10];
void init(node *R,int &len,int n){len=0;for (int i=2;i<n;i++){pii Dis=MK(dis(MK(A[0][i+1],A[1][i+1]),MK(A[0][i],A[1][i])),dis(MK(A[0][i],A[1][i]),MK(A[0][i-1],A[1][i-1])));complex x(A[0][i-1]-A[0][i],A[1][i-1]-A[1][i]),y(A[0][i+1]-A[0][i],A[1][i+1]-A[1][i]);R[++len].insert(Dis,MK(x*y,x/y));}
}
bool Dif[N+10];
node R[N+10],tmp[N+10];
int main(){int n=read(),m=read(),len;for (int i=1;i<=m;i++){Len[i]=read();for (int j=1;j<=Len[i];j++) A[0][j]=read(),A[1][j]=read();if (Len[i]<3) continue;init(R,len,Len[i]);AC.insert(R,len,i);for (int j=1;j<=Len[i];j++) A[1][j]=-A[1][j];init(tmp,len,Len[i]);for (int j=1;j<=len;j++) Dif[i]|=(R[j]!=tmp[j]);Dif[i]^=1;}AC.make_fail();for (int i=1;i<=n;i++) A[0][i]=read(),A[1][i]=read();if (n>2){init(R,len,n),AC.work(R,len);for (int i=1;i<=n;i++) A[1][i]=-A[1][i];init(R,len,n),AC.work(R,len);}AC.updata();for (int i=1;i<=m;i++) printf("%d\n",Len[i]==1?n:Len[i]==2?n-1:Ans[i]>>Dif[i]);return 0;
}
转载于:https://www.cnblogs.com/Wolfycz/p/10574941.html
[ZJOI2008]无序运动Movement相关推荐
- bzoj 1040: [ZJOI2008]骑士 树形dp
题目链接 1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 3054 Solved: 1162 [Submit] ...
- SAP WM初阶LQ02报错 - Movement Type 901 for manual transfer orders does not exist -
SAP WM初阶LQ02报错 - Movement Type 901 for manual transfer orders does not exist - SAP WM模块里的事务代码LQ02很有用 ...
- SAP WM 针对采购订单收货时候不能自动获取物料主数据里的Special Movement Indicator?
SAP WM 针对采购订单收货时候不能自动获取物料主数据里的Special Movement Indicator? SAP WM模块里有一个标记叫做Special Movement Indicator ...
- SAP MM 初阶之Movement Reason
SAP MM 初阶之Movement Reason 对于一些特定的货物移动,业务人员希望能在SAP系统上记录货物移动的原因. 比如对于报废业务,业务人员在每次报废过账的时候希望能指定一个原因,后续可以 ...
- SAP WM Movement Type 里的‘Ref.Stor.Type Search’字段用法初探
SAP WM Movement Type 里的'Ref.Stor.Type Search'字段用法初探 笔者在目前的项目里负责MM以及WM两个模块的实施.根据客户仓库存储区域的现状,我在WM层面的st ...
- SAP VLPOD 报错 - Update control of movement type is incorrect (entry 107 X X E B _ E) - 之对策
SAP VLPOD 报错 - Update control of movement type is incorrect (entry 107 X X E B _ E) - 之对策 如下的DN 8002 ...
- SAP MM Movement Type 503的使用
SAP MM Movement Type 503的使用 SAP里的503移动类型,其描述是:Receipt w/o purchase order into quality inspection sto ...
- bzoj 1037: [ZJOI2008]生日聚会Party
1037: [ZJOI2008]生日聚会Party Description 今天是hidadz小朋友的生日,她邀请了许多朋友来参加她的生日party. hidadz带着朋友们来到花园中,打算 坐成一排 ...
- [ZJOI2008][BZOJ1036] 树的统计count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 7980 Solved: 3266 [Submi ...
最新文章
- MapReduce骚气分析
- Netty面试题 汇总
- Failed to create the Java Virtual Machine
- 通过libusb操作usb设备扫描二维码
- centos安装与配置R语言
- Educational Codeforces Round 16 C. Magic Odd Square 矩阵构造
- exe打包工具哪个最好_为你的 Python 程序写个启动工具箱
- bat复制文件到指定目录同名_scp复制文件时排除指定文件
- 非线性最优化(二)——高斯牛顿法和Levengerg-Marquardt迭代
- 《剑指Offer》 二进制中1的个数
- 设计模式之GOF23迭代器模式
- 习题第一章 构造过程抽象
- Atitit aop的一些资料 目录 2. AOP(面向切面)	1 2.1. 切面(Aspect):其实就是共有功能的实现。如日志切面、权限切面、事务切面等	2 2.2. 通知(Advice
- rs485接口上下拉_带内部上下拉电阻的无极性rs-485接口芯片的制作方法
- 论文查重算法 python_个人项目之论文查重
- 圆和长方形周长相等谁的面积大_周长相等的长方形正方形和圆谁面积最大,谁面...
- 光照模型-PBS在Unity中的应用
- 用matlab实现“太阳-地球-月亮运行示意图”动画
- ES复杂分组同时多聚合统计实现(java)
- 【那些年,我们一起追的女孩】第十六章
热门文章
- C#,欧拉数(Eulerian Number)的算法与源代码
- @click.stop作用(阻止点击事件继续传播,即阻止事件冒泡)
- 面试官的一些问题,给予小伙伴们一些帮助。
- Sony Ericsson W550c
- CentOS8迁移TencentOS 3.1实践
- 7-32 哥尼斯堡的“七桥问题” (欧拉回路)(PAT算法题目集)
- linux多线程_免费Linux下载工具,你还不知道?
- 51单片机基础——数码管数组动态显示0—F
- CyberArk被评为Gartner特权访问管理魔力象限的领导者
- MATLAB 三维画图