听学长说有比赛就随便打一打。

A.普通计算姬

题目大意:给出一棵带权树,支持一下两种操作:1.修改一个点的权值;2.给出l,r,询问以点l为根的子树和、点l+1为根的子树和、点l+2为根的子树和……点r为根的子树和的总和。(点数、操作数不超过10^5)

思路:感觉是三题中最难的。给出的[l,r]区间在树上没有实际意义,不好利用数据结构维护。考虑若不修改,可以一遍dfs算出每个点对应的dfs序,这样每棵子树都对应一个dfs序的区间,前缀和一下就能O(1)查子树和,再按点的编号顺序把子树和前缀和一下就能O(1)回答询问,若要支持修改,我们可以分块重构,每次修改我们先只记录下有这次修改而不实际修改前缀和数组,询问时先利用之前的前缀和数组计算答案,再统计之前每一次修改对这次询问的贡献;每进行K次修改,我们就O(n)重建一遍前缀和数组并删掉记录下的修改。统计修改对询问的贡献可以这么做:将每个子树对应成dfs序区间,统计询问区间内有多少个dfs序区间包含修改点,可以用主席树求出询问区间内有多少dfs序区间右端点大等于修改点,减去有多少dfs序区间左端点大于修改点就得到包含修改点的区间个数,就能计算贡献了。总复杂度O(N^2/K+KNlogN),适当调整K的大小复杂度约为O(N(NlogN)^0.5)。

#include<cstdio>
#define ll unsigned long long
inline int read()
{
int x;char c;
while((c=getchar())<''||c>'');
for(x=c-'';(c=getchar())>=''&&c<='';)x=(x<<)+(x<<)+c-'';
return x;
}
#define MN 100000
#define MK 50
#define ND 4000000
struct edge{int nx,t;}e[MN*+];
struct node{int l,r,s;}t[ND+];
int n,h[MN+],en,z[MN+],l[MN+],r[MN+],cnt,cx[MN+],cy[MN+],cn,tn,rt[MN+];
ll a[MN+],b[MN+];
inline void ins(int x,int y)
{
e[++en]=(edge){h[x],y};h[x]=en;
e[++en]=(edge){h[y],x};h[y]=en;
}
void dfs(int x,int fa)
{
l[x]=++cnt;
for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa)dfs(e[i].t,x);
r[x]=cnt;
}
void build()
{
for(int i=;i<=n;++i)a[l[i]]=z[i];
for(int i=;i<=n;++i)a[i]+=a[i-];
for(int i=;i<=n;++i)b[i]=b[i-]+a[r[i]]-a[l[i]-];
}
void ins(int pr,int pl,int x,int z)
{
for(int l=,r=n,mid,p=rt[pr]=++tn;;)
{
t[p].s=t[pl].s+z;
if(l==r)return;
int mid=l+r>>;
if(x<=mid)t[p].r=t[pl].r,p=t[p].l=++tn,pl=t[pl].l,r=mid;
else t[p].l=t[pl].l,p=t[p].r=++tn,pl=t[pl].r,l=mid+;
}
}
int query(int pl,int pr,int x)
{
int ans=;
for(int l=,r=n,mid;;)
{
if(l==x)return ans+t[pr].s-t[pl].s;
mid=l+r>>;
if(x<=mid)ans+=t[t[pr].r].s-t[t[pl].r].s,pl=t[pl].l,pr=t[pr].l,r=mid;
else pl=t[pl].r,pr=t[pr].r,l=mid+;
}
}
int main()
{
int m,i,t,x,y;ll ans;
n=read();m=read();
for(i=;i<=n;++i)z[i]=read();
for(i=;i<=n;++i)ins(read(),read());
dfs(e[h[]].t,);build();
for(i=;i<=n;++i)ins(i,rt[i-],l[i]-,-),ins(i,rt[i],r[i],);
while(m--)
{
t=read();x=read();y=read();
if(t==)
{
cx[++cn]=l[x];cy[cn]=y-z[x];z[x]=y;
if(cn==MK)cn=,build();
}
if(t==)
{
ans=b[y]-b[x-];
for(i=;i<=cn;++i)ans+=(ll)query(rt[x-],rt[y],cx[i])*cy[i];
printf("%llu\n",ans);
}
}
}

B.文艺计算姬

题目大意:求一边有n个点,另一边有m个点,共n*m条边的二分图共有多少种生成树,答案对p取模。(n,m,p<=10^18)

思路:先用矩阵树定理暴力计算一部分答案,观察容易发现答案为n^(m-1)*m^(n-1),由于模数较大乘法会爆long long,要用类似快速幂的快速乘加上快速幂,复杂度为O(logp^2)。答案公式我还没想到比较好的证明方法,想到了会在这里补上(这类题目一般打表才是比较好的做法)。

矩阵树定理暴力的代码好像被误删了,本来想贴出来的……

#include<cstdio>
#define ll long long
ll n,m,p;
inline ll mod(ll x){return x>=p?x-p:x;}
ll mul(ll a,ll b)
{
ll r=;
for(;b;b>>=,a=mod(a<<))if(b&)r=mod(r+a);
return r;
}
ll pow(ll a,ll b)
{
ll r=;
for(;b;b>>=,a=mul(a,a))if(b&)r=mul(r,a);
return r;
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&p);
printf("%lld",mul(pow(n,m-),pow(m,n-)));
}

C.两双手

题目大意:一个棋子从(0,0)开始走,每次可以从(u,v)走到(u+Ax,u+Ay)或(u+Bx,u+By),有n个点不能走,问走到(Ex,Ey)有多少种方案。(0<=|Ax|,|Ay|,|Bx|,|By|,Ex,Ey,n<=500,Ax*By-Ay*Bx!=0)

思路:比较杂的数学应用吧。考虑容斥原理,走到(Ex,Ey)不经过禁止点的方案=总方案-至少经过一个禁止点的方案+至少经过两个-至少经过三个……可以用DP实现,为了让点有序方便DP,假设先把所有点旋转,使得向量(Ax,Ay)成为x轴,若(Bx,By)旋转后的纵坐标大于0,则一个点可以到另一个当且仅当该点旋转后纵坐标小于另一点旋转后纵坐标,反之同理,按照这个思路排序(实现上比较点积叉积等即可),我们就能保证只有排在前的能到达排在后的。经过奇数个点对答案贡献为负,偶数贡献为正,每次转移取负即可,令f[i]表示到第i个点的答案,则f[i]=Σ-f[j]*g[j][i] (j<i),其中g[j][i]为点j到点i的方案数,初始化(0,0)点的f值为-1即可。下面讨论计算g[j][i],设用了X条(Ax,Ay),Y条(Bx,By),暴力解方程x[j]+AxX+BxY=x[i],y[j]+AyX+ByY=y[i]就能算出X和Y,排列组合一下可以得到方案数,总算大功告成,总复杂度O(n^2)。

#include<cstdio>
#include<algorithm>
using namespace std;
#define MN 500
#define MX 500000
#define MOD 1000000007
int g[MN+][MN+],F[MX+],R[MX+],f[MN+],a,b,c,d,e;
int inv(int x)
{
int r=,y=MOD-;
for(;y;y>>=,x=1LL*x*x%MOD)if(y&)r=1LL*r*x%MOD;
return r;
}
struct node{int x,y;}p[MN+];
bool cmp(node x,node y)
{
int c1=a*x.y-b*x.x,c2=a*y.y-b*y.x;
return c1==c2?a*x.x+b*x.y<a*y.x+b*y.y:e>?c1<c2:c1>c2;
}
int main()
{
int n,i,j,k,A,B,x,y,tx,ty;
for(F[]=i=;i<=MX;++i)F[i]=1LL*F[i-]*i%MOD;
for(R[--i]=inv(F[MX]);i--;)R[i]=1LL*R[i+]*(i+)%MOD;
scanf("%d%d%d",&tx,&ty,&n);p[n+].x=tx;p[n+].y=ty;
scanf("%d%d%d%d",&a,&b,&c,&d);
for(i=;i<=n;++i)scanf("%d%d",&p[i].x,&p[i].y);
e=a*d-b*c;sort(p,p+n+,cmp);
for(i=;i<=n;++i)for(j=i;j++<=n;)
{
A=p[j].x-p[i].x;B=p[j].y-p[i].y;
if((d*A-c*B)%(a*d-c*b))continue;
x=(d*A-c*B)/(a*d-c*b);
if((b*A-a*B)%(c*b-a*d))continue;
y=(b*A-a*B)/(c*b-a*d);
if(x<||y<)continue;
g[i][j]=1LL*F[x+y]*R[x]%MOD*R[y]%MOD;
}
for(i=;i<=n+;++i)
{
if(!p[i].x&&!p[i].y)f[i]=-;
for(j=;j<i;++j)f[i]=(f[i]-1LL*f[j]*g[j][i])%MOD;
if(p[i].x==tx&&p[i].y==ty)return printf("%d",(f[i]+MOD)%MOD),;
}
}

[BZOJ]2017省队十连测推广赛1的更多相关文章

  1. [BZOJ]2017省队十连测推广赛1 T2.七彩树

    题目大意:给你一棵n个点的树,每个点有颜色,m次询问,每次询问一个点x的子树内深度不超过depth[x]+d的节点的颜色数量,强制在线.(n,m<=100000,多组数据,保证n,m总和不超过5 ...

  2. [bzoj省选十连测推广赛2]T2七彩树

    抄自:http://blog.csdn.net/coldef/article/details/61412577 当时看了就不会,看了别人的题解不懂怎么维护,最后抄了个代码....... 给定一棵n个点 ...

  3. bzoj省选十连测推广赛

    A.普通计算姬 题意:给丁一棵树,每个点有一个权值,用sum(x)表示以x为根的子树的权值和,要求支持两种操作: 1 u v  :修改点u的权值为v. 2 l  r   :  求∑sum[i] l&l ...

  4. bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树

    [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 93  Solved: 53[Submit][Status][ ...

  5. bzoj 5216: [Lydsy2017省队十连测]公路建设

    5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 66  Solved: 37[Submit][St ...

  6. Lydsy2017省队十连测

    5215: [Lydsy2017省队十连测]商店购物 可能FFT学傻了,第一反应是前面300*300背包,后面FFT... 实际上前面背包,后面组合数即可.只是这是一道卡常题,需要注意常数.. //A ...

  7. bzoj 5218: [Lydsy2017省队十连测]友好城市

    题意: 这题显然直接tarjan是做不了的. 这里安利另一个求SCC的算法Kosaraju,学习的话可以见这篇博客 于是结合莫队,我们有了个暴力. 发现主要瓶颈是dfs过程中找最小的未经过的点,我们用 ...

  8. 【BZOJ 5222】[Lydsy2017省队十连测]怪题

    题目大意: 传送门 给一个长度为$n(n<=200)$的数列$h$,再给$m$个可以无限使用的操作,第$i$个操作为给长度为花费$c_i$的价值给长度为$l_i$的数列子序列+1或-1,求将数列 ...

  9. bzoj 5217: [Lydsy2017省队十连测]航海舰队

    Description Byteasar 组建了一支舰队!他们现在正在海洋上航行着.海洋可以抽象成一张n×m 的网格图,其中有些位置是" .",表示这一格是海水,可以通过:有些位置 ...

随机推荐

  1. 2018上C语言程序设计(高级)作业- 第2次作业

    作业要求一 提交截图: 6-7: 6-8: 6-9: 7-1: 作业要求二 题目6-7删除字符中数字字符 1.设计思路: (1)第一步:本题要求是删除字符中的数字字符,我的主要思路是通过数组遍历若遇到 ...

  2. mongodb 复制(副本集)

    复制(副本集) 什么是复制 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,并可以保证数据的安全性 复制还允许从硬件故障和服务中断中恢复数据 为什么要复制 数据备份 数据灾 ...

  3. MySQL 操作详解

    MySQL 操作详解 一.实验简介 本节实验中学习并实践 MySQL 上创建数据库.创建表.查找信息等详细的语法及参数使用方法. 二.创建并使用数据库 1. 创建并选择数据库 使用SHOW语句找出服务 ...

  4. Beta集合

    Beta冲刺day1 Beta冲刺day2 Beta冲刺day3 Beta冲刺day4 Beta冲刺day5 Beta冲刺day6 Beta冲刺day7 测试总结 总结合集 Beta预备

  5. linux下面的打包压缩命令

    tar命令 tar [-cxtzjvfpPN] 文件与目录 ....linux下面压缩之前要把一堆文件打个包再压缩,即使只有一个文件也需要打个包.例子:tar czvf 1.tar.gz hello. ...

  6. angular2 学习笔记 ( 4.0 初探 )

    目前是 4.0.0-rc.2. 刚好有个小项目要开发,就直接拿它来试水啦. 更新 cli 到最新版, 创建项目, 然后 follow https://github.com/angular/angula ...

  7. 阿里云API网关(13)请求身份识别:客户端请求签名和服务网关请求签名

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  8. nexus私服服务器意外关机后,本地不能下载jar包

    主要记录一个小问题. 今天要做个需求,需要读取word文档中的表格来在生成数据库建表语句. 读取word文档,要添加maven依赖 <dependency> <groupId> ...

  9. SpringBoot框架中JPA使用的一些问题

    主要是自己在使用JPA框架时遇到的一个坑,拿出来分享一下 首先上一个简单JPA框架实体 public interface EnterpriseInfoDao extends JpaSpecificat ...

  10. POJ-3255 Roadblocks---Dijkstra队列优化+次短路

    题目链接: https://vjudge.net/problem/POJ-3255 题目大意: 给无向图,求1到n的次短路长度 思路: 由于边数较多,应该使用dijkstra的队列优化 用d数组存储最 ...