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

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. 201621123050 《Java程序设计》第7周学习总结

    1. 本周学习总结 1.1 思维导图:Java图形界面总结 2.书面作业 1. GUI中的事件处理 1.1 写出事件处理模型中最重要的几个关键词. 1.事件:用户的操作,例如点击或输入之类的操作 2. ...

  2. webview缓存及跳转时截取url地址、监听页面变化

    缓存及一些设定 我在做一些项目时,h5做的项目手机浏览器能使用,但是在搬到webview时候不能用,这个时候通过查阅资料,原来是webview没有设定好,包括缓存.缓存大小及路径等等 mWebview ...

  3. electron打包vue项目

    electron是什么 Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Electron通过将Chromium和Node.js合并 ...

  4. 快速搭建fabric-v1.1.0的chaincode开发环境

    本文参考了fabric官方文档:http://hyperledger-fabric.readthedocs.io/en/latest/peer-chaincode-devmode.html?highl ...

  5. WebService(1-1)webservice调用

    参考url : http://www.cnblogs.com/flying607/p/6254045.html 今天用动态创建客户端的方式调用webservice,报了这样一个错: 2017-01-0 ...

  6. io使用的设计模式

    File f = new File("c:/a.txt"); 1. FileInputStream fis = new FileInputStream(f); 2. Reader ...

  7. Android TabLayout 在宽屏幕上tab不能平均分配的问题解决

    当TabLayout 在宽屏幕的设备上,如平板横屏的时候,tab的宽度超过一定值后,就不在平均分配宽度,而是居中显示.此时设置 app:tabMode="fixed"或者 top_ ...

  8. Java-Maven(六):Eclipse中Maven插件的命令操作

    之前几个章节学习了maven的概念,及maven插件安装后如何创建工程,那么maven工程中是如何使用maven命令呢?本章节将会学习这个话题. 在pom.xml中配置maven命令插件 如果向在ma ...

  9. property()函数

    class C: def __init__(self, size=10): self.size = size def getXSize(self): return self.size def setX ...

  10. (CLR-Via-C#) 类型基础

    CLR要求每个类型最终都派生自System.Object Object提供的公共方法: Equals: 如果两个对象具有相同的值,就返回true GetHashCode: 返回对象的哈希码 ToStr ...