【2020NOI.AC省选模拟#2】A. 旋转
题目链接
原题解:
把每个点的坐标视为复数,那么每次询问就是区间求平均数(先求和然后除以个数)。一个点绕着原点旋转就是乘以$(\cos 60^\circ +i\sin 60^\circ)$。
一个点绕着某点$A$旋转可以理解为先减去点$A$的坐标,再绕原点旋转,再加上点$A$的坐标。
最终变成用线段树维护复数的序列,支持区间加上一个数和乘上一个数和区间求和,使用打标记的线段树解决。
补充:
在?为什么卡空间?
原题解提供的线段树做法很NICE,然而直接上线段树会被卡空间。然后我百度到了深度好文,学习了线段树少开空间的方法。
首先来个结论:
长度为$n$的序列会形成$2n-1$个节点的线段树。
为啥呢?观察一下线段树的结构,发现有底下的$n$个叶子,之后两个子节点用一个父节点合并。由$n$个连通块合并为一个块需要$n-1$次,所以总共有$2n-1$个节点。
然后我们考虑用DFS序给节点编号。 发现对于节点$i$代表$[l,r]$,左儿子的编号就是$i+1$,然后左子树占用了连续的$2(mid-l+1)-1$个编号,那么右儿子编号就是$i+2(mid-l+1)-1+1=i+2(mid-l+1)$。
然后就过了。打标记的线段树参考我自己的这篇博客。
噢还有一点,就是浮点数要记得重写一个等于函数,本题因为有封装,不容易注意到这个问题,但这确实会导致RE。
代码(100分):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define IL inline
#define RG register
#define _1 first
#define _2 second
using namespace std;
typedef double DB;
#define RI RG int
#define RD RG DB
#define RP RG Pr
#define RM RG Mrk
const int N=1e5;
const DB Pi=acos(-1);
const DB eps=1e-6; int n,q; struct Pr{
DB x,y;
Pr(RD x=0,RD y=0):x(x),y(y){}
}mul1=Pr(1,0),add0=Pr(0,0)
,rot=Pr(cos(Pi/3),sin(Pi/3))
,a[N+3],sum[N*2+3]; IL bool eql(RD x,RD y){
return fabs(x-y)<eps;
} IL bool operator==(RP x,RP y){
return eql(x.x,y.x)&&eql(x.y,y.y);
} IL Pr operator*(RP x,RP y){
return Pr(x.x*y.x-x.y*y.y,x.y*y.x+x.x*y.y);
} IL Pr operator*(RD x,RP y){
return Pr(x*y.x,x*y.y);
} IL Pr operator+(RP x,RP y){
return Pr(x.x+y.x,x.y+y.y);
} struct Mrk{
Pr m,a;
Mrk(RP m=mul1,RP a=add0):m(m),a(a){}
}non,tag[N*2+3]; IL bool operator==(RM x,RM y){
return x.m==y.m&&x.a==y.a;
} IL int ls(RI i){return i+1;}
IL int rs(RI i,RI l,RI mid){
return i+((mid-l+1)<<1);
} IL void f(RI i,RI l,RI r,RM opt){
if(opt==non)
return ; sum[i]=opt.m*sum[i]+(DB)(r-l+1)*opt.a; Mrk tmp=tag[i];
tag[i]=Mrk(opt.m*tmp.m,opt.m*tmp.a+opt.a); } IL void spread(RI i,RI l,RI r){
RI mid=(l+r)>>1;
f(ls(i),l,mid,tag[i]);
f(rs(i,l,mid),mid+1,r,tag[i]);
tag[i]=non; } void build(RI i,RI l,RI r){
tag[i]=non;
if(l==r){
sum[i]=a[l];
return ; } RI mid=(l+r)>>1;
build(ls(i),l,mid);
build(rs(i,l,mid),mid+1,r);
sum[i]=sum[ls(i)]+sum[rs(i,l,mid)]; } void mdf(RI i,RI l,RI r,RI ql,RI qr,RM opt){
if(ql<=l&&r<=qr){
f(i,l,r,opt);
return ; } spread(i,l,r);
RI mid=(l+r)>>1;
if(ql<=mid)
mdf(ls(i),l,mid,ql,qr,opt);
if(qr>mid)
mdf(rs(i,l,mid),mid+1,r,ql,qr,opt);
sum[i]=sum[ls(i)]+sum[rs(i,l,mid)]; } Pr qry(RI i,RI l,RI r,RI ql,RI qr){
if(qr<l||r<ql)
return add0;
if(ql<=l&&r<=qr)
return sum[i]; spread(i,l,r);
RI mid=(l+r)>>1;
if(qr<=mid)
return qry(ls(i),l,mid,ql,qr);
if(ql>mid)
return qry(rs(i,l,mid),mid+1,r,ql,qr);
return qry(ls(i),l,mid,ql,qr)
+qry(rs(i,l,mid),mid+1,r,ql,qr); } int main(){
scanf("%d%d",&n,&q);
for(RI i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y); build(1,1,n);
for(RI i=1,l,r;i<=q;i++){
scanf("%d%d",&l,&r); RP tmp=1.0/(r-l+1)*qry(1,1,n,l,r);
printf("%.10lf %.10lf\n",tmp.x,tmp.y);
mdf(1,1,n,l,r,Mrk(mul1,-1.0*tmp));
mdf(1,1,n,l,r,Mrk(rot,add0));
mdf(1,1,n,l,r,Mrk(mul1,tmp)); } for(RI i=1;i<=n;i++){
a[i]=qry(1,1,n,i,i);
printf("%.10lf %.10lf\n",a[i].x,a[i].y); } return 0; }
【2020NOI.AC省选模拟#2】A. 旋转的更多相关文章
- NOI.AC省选模拟赛第一场 T1 (树上高斯消元)
link 很容易对于每个点列出式子 \(f_{x,y}=(f_{x,y-1}+f_{x,y}+f_{x,y+1}+f_{x+1,y})/4\)(边角转移类似,略) 这个转移是相互依赖的就gg了 不过你 ...
- [NOI.AC省选模拟赛3.31] 星辰大海 [半平面交]
题面 传送门 思路 懒得解释了......也是比较简单的结论 但是自己看到几何就退缩了...... 下周之内写一个计算几何的学习笔记! Code #include<iostream> #i ...
- [NOI.AC省选模拟赛3.31] 附耳而至 [平面图+最小割]
题面 传送门 思路 其实就是很明显的平面图模型. 不咕咕咕的平面图学习笔记 用最左转线求出对偶图的点,以及原图中每个边两侧的点是谁 建立网络流图: 源点连接至每一个对偶图点,权值为这个区域的光明能量 ...
- [NOI.AC省选模拟赛3.30] Mas的童年 [二进制乱搞]
题面 传送门 思路 这题其实蛮好想的......就是我考试的时候zz了,一直没有想到标记过的可以不再标记,总复杂度是$O(n)$ 首先我们求个前缀和,那么$ans_i=max(pre[j]+pre[i ...
- [NOI.AC省选模拟赛3.23] 染色 [点分治+BFS序]
题面 传送门 重要思想 真的是没想到,我很久以来一直以为总会有应用的$BFS$序,最终居然是以这种方式出现在题目中 笔记:$BFS$序可以用来处理限制点对距离的题目(综合点分树使用) 思路 本题中首先 ...
- [NOI.AC省选模拟赛3.23] 集合 [数学]
题面 传送门 一句话题意: 给定$n\leq 1e9,k\leq 1e7,T\leq 1e9$ 设全集$U=\lbrace 1,2,3,...n\rbrace $,求$(min_{x\in S}\lb ...
- [noi.ac省选模拟赛]第12场题解集合
题目 比赛界面. T1 数据范围明示直接\(O(n^2)\)计算,问题就在如何快速计算. 树上路径统计通常会用到差分方法.这里有两棵树,因此我们可以做"差分套差分",在 A 树上对 ...
- [noi.ac省选模拟赛]第10场题解集合
题目 比赛界面. T1 不难想到,对于一个与\(k\)根棍子连接的轨道,我们可以将它拆分成\(k+1\)个点,表示这条轨道不同的\(k+1\)段. 那么,棍子就成为了点与点之间的边.可以发现,按照棍子 ...
- [noi.ac省选模拟赛]第11场题解集合
题目 比赛界面. T1 比较简单.容易想到是求鱼竿的最大独立集.由于题目的鱼竿可以被分割为二分图,就可以想到最大匹配. 尝试建边之后会发现边的数量不小,但联系题目性质会发现对于一条鱼竿,它 ...
- [noi.ac省选模拟赛20200606]赌怪
题目 点这里看题目. 分析 先特判掉\(K=2\)的情况. 首先可以考虑到一个简单 DP : \(f(i)\):前\(i\)张牌的最大贡献. 转移可以\(O(n^2)\)地枚举区间 ...
随机推荐
- 01Java常用类
Object类 Object概述 Object类是超类,基类,所有类都默认直接继承Object类. Object类中定义的方法,是所有对象都具备的方法. Object类可以存储任何类 - 可以作为 ...
- HCIP-进阶实验06-多实例生成树安全部署
HCIP-ICT进阶实验06-多实例生成树安全部署 1 实验需求 1.1 实验拓扑 1.2 实验环境说明 IP地址规划表: 设备 接口 IP 地址 备注 SW1 VLANIF10 192.168.10 ...
- 「postOI」以另一种方式证明 FWT
记号 \(\otimes\) 代表或/与/异或卷积: \(\oplus\) 代表"拼接",例如 \(A\oplus B\) 即将 \(B\) 接在 \(A\) 的后面: \(+,- ...
- java方法的笔记
方法 方法的概念 方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集 注意: 方法必须先创建才可以使用,该过程成为方法定义 方法创建后并不是直接可以运行的,需要手动 ...
- Windows流媒体怎么关闭。
点击白色框,搜索服务. 步骤阅读 步骤阅读 2 选本地服务旁打开,然后下拉服务. 步骤阅读 步骤阅读 3 选择media,然后右键它属性. 步骤阅读 步骤阅读 4 然后点击停止,点击手动. 步骤阅读 ...
- beanshell 响应数据的解析与变量的保存
获取响应的数据 response = prev.getResponseDataAsString() //prev.getResponseDataAsString是Jmeter提供的方法,可以调取上次请 ...
- Linux 第四节(shell脚本,IF,do,for)
Shell脚本 1.批处理式: 2.交互式: 脚本声明 #!/bin/bash 脚本注释 #fakba;kb 脚本命令 ls pwd bash test.sh //执行test.sh脚 ...
- 正整数n型方阵
正整数n型方阵(不用数组完成) 一般呢这种n型方阵很多人都是用数组完成,今天呢小编就用简单的循环控制结构来完成,不需用到数组.题目:从键盘输入一个正整数n,根据n形成一个方阵.方阵最外层是第一层,每层 ...
- Pycharm报错:Error running ‘‘: Cannot run program “\python.exe“ (in directory ““)系统找不到指定文件夹?已解决!
问题报错 报错原因:我修改的工程的名称/或者移动了工程位置,运行导致找不到之前的运行路径 解决办法1.在该项目文件夹下找到一个叫.idea的文件夹.(若没有,选择显示隐藏项目,可能被隐藏了)PyCha ...
- vue ref用法
<div class="myClass" ref="diva"></div> // 给dom节点添加ref this.$refs.div ...
