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

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. github感悟

    刚学GitHub进入网页全英文的,感觉很惊讶,自己竟然要在全英文的网站上学习,虽然是英文的但并不感觉有压力,可能之前用eclipse就是全英文的现在除了惊讶,没太多的想法.然后就是我的GitHub地址 ...

  2. 《javascript设计模式与开发实践》阅读笔记(15)—— 装饰者模式

    装饰者模式 可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象.在程序开发中,许多时候都并不希望某个类天生就非常庞大,一次性包含许多职责.那么我们就可以使用装饰者模式. 代码例 ...

  3. 数据结构与算法 —— 链表linked list(02)

    我们继续来看链表的第二道题,来自于leetcode: 两数相加 给定两个非空链表来代表两个非负整数,位数按照逆序方式存储,它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了 ...

  4. 业余草基于JAVA的模块化开发框架JarsLink

    需求背景 应用拆分的多或少都有问题.多则维护成本高,每次发布一堆应用.少则拆分成本高,无用功能很难下线.故障不隔离.当一个系统由多人同时参与开发时,修改A功能,可能会影响B功能,引发故障.多分支开发引 ...

  5. Python内置函数(1)——abs

    英文文档: abs(x) Return the absolute value of a number. The argument may be an integer or a floating poi ...

  6. vuex在项目中使用的一点总结

    以下为vue后台管理项目中使用vuex的一点总结,截取了其中部分代码,如有什么错误,还望指出. 1. token 存储 登陆成功之后,需要把获取到的 token 存储到 vuex 中,配合 axios ...

  7. javascript学习(2)修改html元素和提示对话框

    一.修改html元素 1.修改p元素 1.1.源代码 1.2.执行前 1.3.执行后 2.修改div元素的className 2.1.源代码 1.2.执行前 1.3.执行后 3.直接在当前位置输出内容 ...

  8. Lumen框架搭建指南

    新人从java转php,到新公司搭建lumen框架,lumen官方文档的坑不是一般的多,对新手极其不友好,记录下我搭建过程,希望对小白们有所帮助. 首先看下官方文档:https://lumen.lar ...

  9. ECSHOP3.6版 钻石小鸟模板修改教程

    ecshop3.6版 钻石小鸟 模板修改明细 (1) 钻石小鸟 首页轮播图修改 (2)首页布局设置 (修改前建议先备份下数据库.  后台/数据备份) (3)修改模板头部内容. 如下图. 后台,模板设置 ...

  10. Collections、Arrays 简明

    Collections : 它的出现给集合操作提供了更多的功能.这个类不需要创建对象,内部提供的都是静态方法. 一般方法 Collections. sort (list); list 集合进行元素的自 ...