CF611G New Year and Cake
XXVII.CF611G New Year and Cake
做题时居然忘记了叉积满足分配律/jk
我们先将图形翻转成为逆时针排布。
首先,我们发现,若总图形的面积是 ,切完后,较小一半的面积是 ,则贡献是 。
我们记点 构成的图形为
于是我们对于每个 ,考虑求出其后方最后一个 ,使得 。(当然,这里的 是循环意义下的)。按照套路,这应该用two-pointers就能轻松解决。
然后,对于每一个 , 都能作为 被计算。
于是我们现在要求出 。拆开,得到 。
前一半很好算,关键是后一半。随着右边界 的增加,此和是很好维护的;但是,当左边界 增加时,和就不太好维护了。
我们考虑,当 增加 时,,减少 。其可被表示成 。
考虑不同的 ,因为叉积满足分配律,所以当 增加 时,后面的东西减少了
再拆,得到
明显此处 内的东西就很好维护了,于是我们原本想维护的那一大坨也就可以维护了。
复杂度 。
(注意,当比较面积是否超过 时,此处的面积不能取模;然而,其它时候(特别是维护 的时候),模是一定要取的,所以解决方案是写一套自动取模的向量模板,再写一套不取模的)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod=1e9+7;
int n,res;
struct MV{//moduloed vector
int x,y;
MV(){x=y=0;}
MV(int X,int Y){x=(X+mod)%mod,y=(Y+mod)%mod;}
friend MV operator +(const MV &u,const MV &v){return MV((u.x+v.x)%mod,(u.y+v.y)%mod);}
friend MV operator -(const MV &u,const MV &v){return MV((u.x+mod-v.x)%mod,(u.y+mod-v.y)%mod);}
friend MV operator *(const MV &u,const int &v){return MV(1ll*u.x*v%mod,1ll*u.y*v%mod);}
friend int operator &(const MV &u,const MV &v){return (1ll*u.x*v.y%mod-1ll*u.y*v.x%mod+mod)%mod;}//cross times
friend int operator |(const MV &u,const MV &v){return (1ll*u.x*v.x%mod+1ll*u.y*v.y%mod)%mod;}//point times
void operator +=(const MV &v){(x+=v.x)%=mod,(y+=v.y)%=mod;}
void operator -=(const MV &v){(x+=mod-v.x)%=mod,(y+=mod-v.y)%=mod;}
void read(){scanf("%d%d",&x,&y),(x+=mod)%=mod,(y+=mod)%=mod;}
void print(){printf("(%d,%d)",x,y);}
}q[500100];
struct OV{//ordinary vector
int x,y;
OV(){}
OV(int X,int Y){x=X,y=Y;}
friend OV operator +(const OV &u,const OV &v){return OV(u.x+v.x,u.y+v.y);}
friend OV operator -(const OV &u,const OV &v){return OV(u.x-v.x,u.y-v.y);}
friend ll operator &(const OV &u,const OV &v){return 1ll*u.x*v.y-1ll*u.y*v.x;}//cross times
friend ll operator |(const OV &u,const OV &v){return 1ll*u.x*v.x+1ll*u.y*v.y;}//point times
void read(){scanf("%d%d",&x,&y);}
void print(){printf("(%d,%d)",x,y);}
}p[500100];
ull area;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)p[n-i].read(),q[n-i]=MV(p[n-i].x,p[n-i].y);
for(int i=0;i<n;i++)area+=p[i]&p[(i+1)%n];
ull nowarea=0;
int sumarea=0;
MV v;
for(int i=0,j=0;i<n;i++){
while(((nowarea+((p[j]-p[i])&(p[(j+1)%n]-p[i])))<<1)<=area){
v+=q[(j+1)%n];
nowarea+=(p[j]-p[i])&(p[(j+1)%n]-p[i]);
(sumarea+=nowarea%mod)%=mod;
(++j)%=n;
}
(res+=(area%mod*((j-i+n-1)%n)%mod-2*sumarea%mod+mod)%mod)%=mod;
nowarea-=(p[(i+1)%n]-p[i])&(p[j]-p[i]),v-=q[(i+1)%n];
(sumarea+=mod-((q[(i+1)%n]-q[i])&(v-q[i]*((j-i+n-1)%n)))%mod)%=mod;
}
printf("%d\n",res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?