题目链接

原题解:

把每个点的坐标视为复数,那么每次询问就是区间求平均数(先求和然后除以个数)。一个点绕着原点旋转就是乘以$(\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. 旋转的更多相关文章

  1. NOI.AC省选模拟赛第一场 T1 (树上高斯消元)

    link 很容易对于每个点列出式子 \(f_{x,y}=(f_{x,y-1}+f_{x,y}+f_{x,y+1}+f_{x+1,y})/4\)(边角转移类似,略) 这个转移是相互依赖的就gg了 不过你 ...

  2. [NOI.AC省选模拟赛3.31] 星辰大海 [半平面交]

    题面 传送门 思路 懒得解释了......也是比较简单的结论 但是自己看到几何就退缩了...... 下周之内写一个计算几何的学习笔记! Code #include<iostream> #i ...

  3. [NOI.AC省选模拟赛3.31] 附耳而至 [平面图+最小割]

    题面 传送门 思路 其实就是很明显的平面图模型. 不咕咕咕的平面图学习笔记 用最左转线求出对偶图的点,以及原图中每个边两侧的点是谁 建立网络流图: 源点连接至每一个对偶图点,权值为这个区域的光明能量 ...

  4. [NOI.AC省选模拟赛3.30] Mas的童年 [二进制乱搞]

    题面 传送门 思路 这题其实蛮好想的......就是我考试的时候zz了,一直没有想到标记过的可以不再标记,总复杂度是$O(n)$ 首先我们求个前缀和,那么$ans_i=max(pre[j]+pre[i ...

  5. [NOI.AC省选模拟赛3.23] 染色 [点分治+BFS序]

    题面 传送门 重要思想 真的是没想到,我很久以来一直以为总会有应用的$BFS$序,最终居然是以这种方式出现在题目中 笔记:$BFS$序可以用来处理限制点对距离的题目(综合点分树使用) 思路 本题中首先 ...

  6. [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 ...

  7. [noi.ac省选模拟赛]第12场题解集合

    题目 比赛界面. T1 数据范围明示直接\(O(n^2)\)计算,问题就在如何快速计算. 树上路径统计通常会用到差分方法.这里有两棵树,因此我们可以做"差分套差分",在 A 树上对 ...

  8. [noi.ac省选模拟赛]第10场题解集合

    题目 比赛界面. T1 不难想到,对于一个与\(k\)根棍子连接的轨道,我们可以将它拆分成\(k+1\)个点,表示这条轨道不同的\(k+1\)段. 那么,棍子就成为了点与点之间的边.可以发现,按照棍子 ...

  9. [noi.ac省选模拟赛]第11场题解集合

    题目   比赛界面. T1   比较简单.容易想到是求鱼竿的最大独立集.由于题目的鱼竿可以被分割为二分图,就可以想到最大匹配.   尝试建边之后会发现边的数量不小,但联系题目性质会发现对于一条鱼竿,它 ...

  10. [noi.ac省选模拟赛20200606]赌怪

    题目   点这里看题目. 分析   先特判掉\(K=2\)的情况.   首先可以考虑到一个简单 DP :   \(f(i)\):前\(i\)张牌的最大贡献.   转移可以\(O(n^2)\)地枚举区间 ...

随机推荐

  1. 安装 Harbor

    安装Harbor先决条件 https://goharbor.io/docs/2.6.0/install-config/installation-prereqs/ 1.安装docker 参考docker ...

  2. memoの左手转右手

    说的是坐标系. 假设两个坐标系都是X向右,Y向上.那么,右手系的Z是从屏幕垂直向外,左手系的Z就是垂直屏幕向里. 向量假设是列向量.(OpenGL系的毛病啊,列向量,右手系,泪目) 先说结论 变换矩阵 ...

  3. 【Linux】有名管道实现进程间通信——一个简单聊天程序

    有名管道实现简单聊天程序 1. "你来我往"式简单聊天 函数功能:简单聊天程序,两个程序a和b,a向b发送信息,b接收信息,b向a发送信息,a接收信息:... 源码参考: chat ...

  4. 如何理解Vue中的组件?

    Vue2.6已经更新了关于内容插槽和作用域插槽的API和用法,为了不误导大家,我把插槽的内容删除了.详情请看官网 2018-07-19更新: 更新作用域插槽的属性: scope -> slot- ...

  5. 二、chaosblade实现k8s集群操作

    1.执行 Kubernetes 实验场景,需要提前部署 ChaosBlade Operator,Helm 安装包下载地址 https://github.com/chaosblade-io/chaosb ...

  6. mybatis-plus 时间查询

    QueryWrapper userquery= new QueryWrapper<>(); user.and(true,wrapper -> wrapper.ge("CRE ...

  7. 【Hive】元数据库部署的三种方式和选择【metaStore server】

    一.Derby 元数据使用之前,要在hive目录下执行schematool命令,进行初始化设置 bin/schematool -dbType derby -initSchema 启动hive后,可以用 ...

  8. npm vue-router安装报错

    因为2022年2月7日以后,vue-router的默认版本,为4版本,而且 vue-router4,只能在vue3中,只有vue-router3中,能用在vue 2中 如果把vue-router4强制 ...

  9. postgresql源码解读

    大量模块源码解读 https://blog.csdn.net/cuichao1900?type=blog 存储管理(内存管理.外存管理)源码解读,每行都有注释 https://blog.csdn.ne ...

  10. oracle ebs 账户组合验证

    DECLARE l_segment1 GL_CODE_COMBINATIONS.SEGMENT1%TYPE; l_segment2 GL_CODE_COMBINATIONS.SEGMENT2%TYPE ...