A.普通计算姬

题意:给丁一棵树,每个点有一个权值,用sum(x)表示以x为根的子树的权值和,要求支持两种操作:

1 u v  :修改点u的权值为v。

2 l  r   :  求∑sum[i] l<=i<=r

n,m(操作数)<=10^5

题解:数据范围比较小,考虑分块重建的做法。

求出每个点的dfs序和子树的区间,这样就可以On建出所有节点的sum的前缀和。

然后每次修改操作都把操作存下来,每次查询先找出这段区间的和,再去操作里处理这些操作对这个查询的影响。

具体实现就是:把每个点的子树的dfs序范围的左右端点都扔到一棵主席树里面,每次查询一个区间时候,枚举修改操作,在主席树里面查询,修改操作修改的点影响的子树数量就=右端点大等于它的dfs序的数量-左端点大于它的dfs序的数量。

然后当操作达到一定数量的时候,暴力On重建一发。

如果操作达到k时候重建,那么复杂度就大概是n^2/k+nklogn,题目有4s,很科学。

然后这破题写了好久,还wa了好多次,代码丑。

#include<iostream>
#include<cstdio>
#include<cmath>
#define ll unsigned long long
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} long long q[],q2[];
int top=;
long long b[];
ll sum[],num[];
int rt1[],rt2[];
int op,u,v,cnt=,n,m,dn=,cc=,rt,head[];
struct edge{
int to,next;
}e[];
int nl[],nr[];
ll ans=; struct TREE{
int l,r,x;
}T[]; void ins(int f,int t)
{
e[++cnt].next=head[f];head[f]=cnt;
e[cnt].to=t;
} int query(int x,int ad)
{
// cout<<"query"<<x<<" "<<ad<<endl;
if(ad>n||x==) return ;
int l=,r=n,sum=;
while(l<r&&x)
{
// cout<<l<<" "<<r<<" "<<x<<" "<<sum<<endl;
int mid=(l+r)>>;
if(ad<=mid)
{sum+=T[T[x].r].x;x=T[x].l;r=mid;}
else
{x=T[x].r;l=mid+;}
}
//cout<<sum<<" "<<T[x].x<<endl;
return sum+T[x].x;
} void inst(int x,int ls,int ad)
{
// cout<<"inst"<<x<<" "<<ls<<" "<<ad<<endl;
int l=,r=n;
while(l<r)
{
int mid=(l+r)>>;
if(ad<=mid)
{
T[x].l=++cc;T[x].r=T[ls].r;T[x].x=T[ls].x+;
r=mid;x=T[x].l;ls=T[ls].l;
}
else
{
T[x].r=++cc;T[x].l=T[ls].l;T[x].x=T[ls].x+;
l=mid+;x=T[x].r;ls=T[ls].r;
}
// cout<<l<<" "<<r<<" "<<x<<" "<<ls<<endl;
}
T[x].x=T[ls].x+;
} void dfs(int x,int fa)
{
nl[x]=++dn;
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fa)
dfs(e[i].to,x);
nr[x]=dn;
} void rebuild()
{
top=;
for(int i=;i<=n;i++)b[nl[i]]=num[i];
for(int i=;i<=n;i++)b[i]+=b[i-];
for(int i=;i<=n;i++)sum[i]=sum[i-]+b[nr[i]]-b[nl[i]-];
} void init()
{
dfs(rt,);
// for(int i=1;i<=n;i++) cout<<i<<" "<<nl[i]<<" "<<nr[i]<<endl;
for(int i=;i<=n;i++)
{
rt1[i]=++cc;rt2[i]=++cc;
inst(rt1[i],rt1[i-],nl[i]),inst(rt2[i],rt2[i-],nr[i]);
}
} int main()
{
n=read();m=read();
for(int i=;i<=n;i++)
num[i]=read();
for(int i=;i<=n;i++)
{
u=read();v=read();
if(u==){rt=v;continue;}
ins(u,v);ins(v,u);
}init();rebuild();
for(int i=;i<=m;i++)
{
op=read();u=read();v=read();
if(op==){q[++top]=u;q2[top]=v-num[u];num[u]=v;}
else
{
ans=sum[v]-sum[u-];
for(int j=;j<=top;j++)
{
ans+=1LL*q2[j]*(query(rt2[v],nl[q[j]])-query(rt2[u-],nl[q[j]])
-query(rt1[v],nl[q[j]]+)+query(rt1[u-],nl[q[j]]+));
}
printf("%llu\n",ans);
}
if(top>=)
rebuild();
}
return ;
}

B.文艺计算姬

题意:求一个一边有n个点,另一边有m个点的完全二分图的生成树数量%p     n,m,p<=10^18

题解:观察之后发现:答案是n^(m-1)*m^(n-1) 由于n,m非常大,所以手写一个大整数乘法就行了。

顺便一说,ditoly 0ms+代码短卡到rank1了,真的劲。复杂度(log^2n)

#include<iostream>
#include<cstdio>
#define ll unsigned long long
using namespace std;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} ll n,m,p; ll mul(ll a,ll b,ll mod)
{
ll sum=;
for(;b;b>>=,a=(a<<)%mod)if(b&)sum=(sum+a)%mod;
return sum;
} ll pow(ll x,ll p,ll mod)
{
ll sum=;
for(ll i=x;p;p>>=,i=mul(i,i,mod))
if(p&) sum=mul(sum,i,mod);
return sum;
} int main()
{
n=read();m=read();p=read();
ll ans=mul(pow(n,m-,p),pow(m,n-,p),p);
cout<<ans;
return ;
}

C.有一个点位于(0,0),你要把它移到(ex,ey),有两种可用的移动,如果原来位于(x,y)的话分别可以让他移动到(x+a,y+b)和(x+c,y+d)a*d-b*c!=0

还有n个点是限制点,不能走,求移动的方案数。  n<=500,限制点的坐标绝对值<=500

题解: 考虑dp+容斥原理,预处理(解方程+组合数)出每两个点之间的方案数量,答案=方案数-走一个限制点的方案数+走两个限制点的方案-........

但这显然要求转移是有序的,我们发现题目只有两种可用的移动,所以我们可以考虑以其中一个向量为x轴,然后按照y坐标为第一关键字,x坐标为第二关键字乱排序一下(可以利用向量的点积和叉积),然后直接dp就没啦。

复杂度(nlogn+n^2)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define mod 1000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} ll q[],r[];
ll f[];
ll g[][];
double xie;
int a,b,c,d;
int ex,ey,n;
struct node{
int x,y,nx,ny;
}s[]; bool cmp1(node xx,node yy){return xx.nx<yy.nx||(xx.nx==yy.nx&&xx.ny<yy.ny);}
bool cmp2(node xx,node yy){return xx.nx>yy.nx||(xx.nx==yy.nx&&xx.ny<yy.ny);} ll solve(int x,int y)
{
/*
a*x1+c*x2=x
b*x1+d*x2=y
ab*x1+cb*x2=xb
ab*x1+ad*x2=ya
(ad-cb)*x2=ya-xb;
x2=(yx-xb)/(da-cb)
ad*x1+cd*x2=xd
bc*x1+dc*x2=yc
(bc-ad)x1=yc-xd
*/
int x2=a*y-x*b,y2=d*a-c*b;
int x1=y*c-x*d,y1=b*c-a*d;
// cout<<x<<" "<<y<<" "<<x2<<" "<<y2<<" "<<x1<<" "<<y1<<endl;
if(x2%y2!=||x1%y1!=)return ;
x2/=y2;x1/=y1;
if(x1<||x2<)return ;
ll sum=q[x1+x2]*r[x1]%mod*r[x2]%mod;
return sum;
} int main()
{
q[]=;r[]=;q[]=r[]=;
for(int i=;i<=;i++){q[i]=q[i-]*i%mod;r[i]=(mod-(mod/i))%mod*r[mod%i]%mod;}
for(int i=;i<=;i++)r[i]=r[i]*r[i-]%mod;
ex=read();ey=read();n=read();
a=read();b=read();c=read();d=read();
s[].x=s[].y=;s[n+].x=ex;s[n+].y=ey;
s[].nx=;s[n+].nx=ey*a-ex*b;
s[].ny=;s[n+].ny=ex*a+ey*b;
for(int i=;i<=n+;i++)
{ s[i].x=read();s[i].y=read();
s[i].nx=a*s[i].y-s[i].x*b;
s[i].ny=s[i].x*a+s[i].y*b;
}
n+=;
if(a*d-b*c<)sort(s+,s+n,cmp2);
else sort(s+,s+n,cmp1);
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++)
g[i][j]=solve(s[j].x-s[i].x,s[j].y-s[i].y);
f[]=-;
for(int i=;i<=n;i++)
for(int j=;j<i;j++)
f[i]=(f[i]-g[j][i]*f[j])%mod;
while(f[n]<)f[n]+=mod;
cout<<f[n];
return ;
}

bzoj省选十连测推广赛的更多相关文章

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

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

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

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

  3. [BZOJ]2017省队十连测推广赛1

    听学长说有比赛就随便打一打. A.普通计算姬 题目大意:给出一棵带权树,支持一下两种操作:1.修改一个点的权值:2.给出l,r,询问以点l为根的子树和.点l+1为根的子树和.点l+2为根的子树和--点 ...

  4. 【省选十连测之九】【DP】【组合计数去重】【欧拉函数】基本题

    目录 题意: 输入格式: 输出格式: 数据范围: 思路: 嵌套题的转移 基本题的转移 Part1 Part2 Part3 代码 题意: 这是一个关于括号组合的题. 首先定义一道题是由'(',')',' ...

  5. 【省选十连测之一】【线段树】【最小生成树之Kruskal】公路建设

    目录 题意 输入格式 输出格式 数据范围 思路 代码 题意 有n个点,m条双向道路,其中第条公路的两个端点是u[i],v[i],费用是c[i]. 现在给出q个询问,每次给定一个L和一个R,要求你只能够 ...

  6. 【正睿oi省选十连测】第一场

    四小时写了两个暴力??自闭 [原来这就是神仙们的分量Orz rank 56/75 可以说是无比垃圾了 下周目标:进步十名?[大雾 T1 题意:有n个点的图 点有点权Ai 也有点权Bi = A_1 + ...

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

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

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

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

  9. ZROI2019 提高十连测

    额 掰手指头一数 特么又是第三年十连测了= = 2017一场没打 那时候好像一场比赛也就100人左右 2018前几场还都好好补了 后来开始放飞自我了 这时候一场有150人还多了 2019想让今年的No ...

随机推荐

  1. 【iOS】Swift GCD-上

    尽管Grand Central Dispatch(GCD)已经存在一段时间了,但并非每个人都知道怎么使用它.这是情有可原的,因为并发很棘手,而且GCD本身基于C的API在Swift世界中很刺眼. 在这 ...

  2. 关于mule中Spring使用中的一个问题

    在mule中连接数据库时,大家通常喜欢使用spring的数据库连接以及bean的配置,但是在使用时会出现一些问题,即bean无法找到,这些,就是需要把bean的id属性改成name属性:可能是因为mu ...

  3. DELL EqualLogic PS存储硬盘故障数据恢复成功案例分享

    DELL EqualLogic PS4000采用虚拟ISCSI SAN阵列,为远程或分支办公室.部门和中小企业存储部署带来企业级功能.智能化.自动化和可靠性.以简化的管理.快速的部署及合理的价格满足了 ...

  4. CentOS 7 GUI图形界面安装

    在此之前先获取root权限,进行以下命令: 1. 在命令行下输入下面的命令来安装Gnome包: yum groupinstall "GNOME Desktop" "Gra ...

  5. Python内置函数(63)——property

    英文文档: class property(fget=None, fset=None, fdel=None, doc=None) Return a property attribute. fget is ...

  6. 网络IO超时的几种实现

    一.select/poll/epoll int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,str ...

  7. RSA的公钥、私钥

    一.举个例子 1.发消息 用对方的公钥给对方发消息 2.发公告 发公告的时候,用自己的私钥形成签名! 二.加密和签名 RSA的公钥.私钥是互相对应的,RSA会生成两个密钥,你可以把任何一个用于公钥,然 ...

  8. Java设计模式(七)Decorate装饰器模式

    一.场景描述 (一)问题 系统中最初使用Crystal Report(水晶报表)工具生成报表,并将报表发送给客户端查看,此时定义一CrystalReport工具类即可完成水晶报表的生成工作. 后续报表 ...

  9. express实践(一)

    涉及以下这些内容: 主体. cookie.session 数据 模板引擎 服务器基本结构: const express=require('express'); const static=require ...

  10. 前端之CSS内容

    一.CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). 二.CSS语法 1 ...