期望得分:100+100+40=240

实际得分:100+0+40=140

二进制拆分、二进制前缀和

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
#define N 100001
int a[N],b[N],c[N];
const int mod=1e9+;
int suma[N][],sumb[N][];
int bit[];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
int finda(int r,int wh)
{
long long tot=;
for(int i=;i<=;i++)
if(wh&bit[i]) tot=(tot+1ll*(r-suma[r][i])*bit[i])%mod;
else tot=(tot+1ll*suma[r][i]*bit[i])%mod;
return int(tot%mod);
}
int findb(int r,int wh)
{
long long tot=;
for(int i=;i<=;i++)
if(wh&bit[i]) tot=(tot+1ll*(r-sumb[r][i])*bit[i])%mod;
else tot=(tot+1ll*sumb[r][i]*bit[i])%mod;
return int(tot%mod);
}
int main()
{
freopen("xorarray.in","r",stdin);
freopen("xorarray.out","w",stdout);
int n;
scanf("%d",&n);
int len,x;
for(int i=;i<=n;i++)
{
read(a[i]);
len=; x=a[i];
while(x) suma[i][len++]=suma[i-][len]+(x&),x/=;
for(int j=len;j<=;j++) suma[i][j]=suma[i-][j];
}
for(int i=;i<=n;i++)
{
read(b[i]);
len=; x=b[i];
while(x) sumb[i][len++]=sumb[i-][len]+(x&),x/=;
for(int j=len;j<=;j++) sumb[i][j]=sumb[i-][j];
}
bit[]=;
for(int i=;i<=;i++) bit[i]=bit[i-]<<;
c[]=a[]^b[];
for(int k=;k<=n;k++)
{
c[k]=c[k-];
c[k]=(c[k]+finda(k-,b[k]))%mod;
c[k]=(c[k]+findb(k,a[k]))%mod;
}
for(int i=;i<=n;i++) printf("%d ",c[i]);
}

60分做法:

先做一遍最小生成树

枚举两个点i,j,那么替换掉的是最小生成树上i,j路径上权值最大的边

倍增维护

时间复杂度:O(n*n*logn)

100分做法:

换一个角度,考虑被替换掉的边的贡献

边e要想被替换掉,那么点 i,j 要满足两个条件:

① 设e的两端点为u,v,i∈u,j∈v

② e的边权是连通 i,j 必经之路(最短路)上边权最大的边

怎么找这条边?——Kruscal算法

Kruscal算法每次找还没有加进去的权值最小的边,所以满足必经之路

还没有加进去的边权最小的边,是已加进去的边权最大的边,所以满足路径上边权最大

所以,设最小生成树的总权值为sum,设当前边权为w,当前边连接的两点的集合大小分别为 s1、s2

ans=(sum*n*(n-1)- 2*Σ s1*s2*w)/(n*(n-1))

n*(n-1):任意选两个点共有这些选法

Σ 前乘2:u,v 和 v,u 算不同的方案

#include<cstdio>
#include<algorithm>
#define N 20001
#define M 100001
using namespace std;
typedef long long LL;
int fa[N],siz[N];
struct node
{
int u,v,w;
}e[M];
bool cmp(node p,node q)
{
return p.w<q.w;
}
int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }
int main()
{
freopen("detective.in","r",stdin);
freopen("detective.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e+,e+m+,cmp);
for(int i=;i<=n;i++) fa[i]=i,siz[i]=;
int u,v;
LL sum=,cnt=;
for(int i=;i<=m;i++)
{
u=find(e[i].u); v=find(e[i].v);
if(u==v) continue;
sum+=e[i].w;
cnt+=1ll*siz[u]*siz[v]*e[i].w;
fa[v]=u; siz[u]+=siz[v];
}
printf("%.2lf",sum-cnt*2.0/(n*(n-)));
}

考场上替换掉的不是 i,j 路径上权值最大的边,替换的是与i,j相连的边权最大的边,0分。

连接i,j 之后,要满足还是一颗树,去掉i,j之间的任意一条边即可

分治+DP+bitset

若点(x1,y1)能访问到点(x2,y2)

假设x1<=x2,y1<=y2

那么(x1,y1)往右下扩展,(x2,y2)往左上扩展,两个点一定在中间某一行相遇

所以可以利用分治的思想枚举相遇的那一行

如果x1和x2都在枚举的这一行的上面,那就扔到左边

如果x1和x2都在枚举的这一行的下面,那就扔到右边

左边和右边的分别继续分治下去

如果x1和x2一个在上面,一个在下面,那就判断这两个点能否在这一行相遇

能在这一行相遇,两个点一定能相遇

反之,一定不能相遇

如何判断 ?

假设当前枚举的相遇行为mid,

f[i][j][k]=0/1表示第i行第j列的点,向右下扩展,能否扩展到第mid行的第k列

g[i][j][k]=0/1表示第i行第j列的点,向左上扩展,能否扩展到第mid行的第k列

若 f[x1][y1][k] 和 g[i][j][k] 有一个k同时为true,那么两个点就可以相遇

第三维可以用bitset简化

f的转移:

预处理:f[mid][j][j]=第mid行第j列是否有障碍

倒叙枚举mid行之上的i,j,f[i][j]|=f[i][j+1],f[i][j]|=f[i+1][j]

g的转移类似,

正序枚举mid行之下的,加号改成减号即可

#include<cstdio>
#include<vector>
#include<bitset>
#define N 501
#define M 1000001
using namespace std;
int n,m;
bool mp[N][N],ans[M];
char s[N];
bitset<N>f[N][N],g[N][N];
struct node
{
int sx,sy,tx,ty,id;
};
node p;
void solve(vector<node>v,int l,int r)
{
if(l>r) return;
int mid=l+r>>;
for(int i=mid;i>=l;i--)
for(int j=m;j;j--)
{
f[i][j]=;
if(!mp[i][j]) continue;
if(i==mid) f[i][j].set(j);
else f[i][j]|=f[i+][j];
if(j!=m) f[i][j]|=f[i][j+];
}
for(int i=mid;i<=r;i++)
for(int j=;j<=m;j++)
{
g[i][j]=;
if(!mp[i][j]) continue;
if(i==mid) g[i][j].set(j);
else g[i][j]|=g[i-][j];
if(j!=) g[i][j]|=g[i][j-];
}
vector<node>vl,vr;
for(vector<node>::iterator it=v.begin();it!=v.end();it++)
{
p=*it;
if(p.tx<mid) vl.push_back(p);
else if(p.sx>mid) vr.push_back(p);
else ans[p.id]=(f[p.sx][p.sy]&g[p.tx][p.ty]).any();
}
solve(vl,l,mid-);
solve(vr,mid+,r);
}
int main()
{
freopen("boardgame.in","r",stdin);
freopen("boardgame.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",s+);
for(int j=;j<=m;j++) mp[i][j]= s[j]=='.' ? true : false;
}
int Q;
scanf("%d",&Q);
vector<node>v;
for(int i=;i<=Q;i++)
{
scanf("%d%d%d%d",&p.sx,&p.sy,&p.tx,&p.ty);
p.id=i;
v.push_back(p);
}
solve(v,,n);
for(int i=;i<=Q;i++) ans[i] ? puts("Yes") : puts("No");
return ;
}

考场40分双向宽搜,然而跟普通的bfs一个样

#include<cstdio>
#include<iostream>
using namespace std;
#define N 501
bool mp[N][N];
char s[N];
int n,m,rd[N][N][];
int sx,sy,tx,ty;
int vis[N][N];
int q[N*N],h,t,cnt,bl[N][N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
int turn(int i,int j)
{
return (i-)*m+j;
}
bool bfs()
{
cnt++; h=,t=;
q[++h]=turn(sx,sy);
int now,x,y;
vis[sx][sy]=cnt;
vis[tx][ty]=cnt;
q[++t]=turn(tx,ty);
bl[sx][sy]=; bl[tx][ty]=;
while(h<=t)
{
now=q[h++];
x=(now-)/m+; y=now-(x-)*m;
if(bl[x][y]==)
{
if(mp[x+][y])
{
if(bl[x+][y]== && vis[x+][y]==cnt) return true;
if(vis[x+][y]!=cnt) vis[x+][y]=cnt,q[++t]=turn(x+,y),bl[x+][y]=;
}
if(mp[x][y+])
{
if(bl[x][y+]== && vis[x][y+]==cnt) return true;
if(vis[x][y+]!=cnt) vis[x][y+]=cnt,q[++t]=turn(x,y+),bl[x][y+]=;
}
}
else
{
if(mp[x-][y])
{
if(bl[x-][y]== && vis[x-][y]==cnt) return true;
if(vis[x-][y]!=cnt) vis[x-][y]=cnt,q[++t]=turn(x-,y),bl[x-][y]=;
}
if(mp[x][y-])
{
if(bl[x][y-]== && vis[x][y-]==cnt) return true;
if(vis[x][y-]!=cnt) vis[x][y-]=cnt,q[++t]=turn(x,y-),bl[x][y-]=;
}
}
}
return false;
}
int main()
{
freopen("boardgame.in","r",stdin);
freopen("boardgame.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",s+);
for(int j=;j<=m;j++) mp[i][j]=s[j]=='.' ? true : false;
}
int q;
scanf("%d",&q);
while(q--)
{
read(sx); read(sy); read(tx); read(ty);
if(!mp[sx][sy] || !mp[tx][ty]) { puts("No"); continue; }
if(sx==tx && sy==ty) { puts("Yes"); continue; }
if(tx<=sx && ty<=sy) { puts("No"); continue; }
if(bfs()) puts("Yes");
else puts("No");
}
}

2017北京国庆刷题Day6 afternoon的更多相关文章

  1. 2017北京国庆刷题Day1 afternoon

    期望得分:100+100+100=300 实际得分:100+100+100=300 T1 一道图论好题(graph) Time Limit:1000ms   Memory Limit:128MB 题目 ...

  2. 2017北京国庆刷题Day5 afternoon

    期望得分:100+60+100=260 实际得分:0+60+40=100 设图中有m个环,每个环有si条边,有k条边不在环中 ans= (2^s1 -2)*( 2^s2 -2)* (2^s3 -2)… ...

  3. 2017北京国庆刷题Day2 afternoon

    期望得分:100+100+50=250 实际得分:100+70+50=220 T1 最大值(max) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一 ...

  4. 2017北京国庆刷题Day4 afternoon

    期望得分:100+100+0=200 实际得分:5+0+0=5 每加入一个数,x的因数位置++ 注意:根号x枚举时,如果x是完全平方数,根号x会重复累计2次,要减去 考场上没减,5分 /(ㄒoㄒ)/~ ...

  5. 2017北京国庆刷题Day3 afternoon

    期望得分:100+0+30=130 实际得分:100+36.5+0=136.5 T3 一个变量写混了,丢了30.. 模拟栈 #include<cstdio> #include<cst ...

  6. 2017北京国庆刷题Day7 afternoon

    期望得分:100+30+100=230 实际得分:60+30+100=190 排序去重 固定右端点,左端点单调不减 考场上用了二分,没去重,60 #include<cstdio> #inc ...

  7. 2017北京国庆刷题Day6 morning

    期望得分:100+100+20=220 实际得分:100+100+20=220 模拟栈 #include<cstdio> #include<cstring> using nam ...

  8. 2017北京国庆刷题Day7 morning

    期望得分:100+0+100=200 实际得分:100+20+0=120 离散化搞搞 #include<cstdio> #include<iostream> #include& ...

  9. 2017北京国庆刷题Day3 morning

    期望得分:100+60+0=160 实际得分:100+30+0=130 考场上用的哈希 #include<cstdio> #include<cstring> #include& ...

随机推荐

  1. 路由器DMZ功能

    环境描述 172.17* 校园网 实验室路由器接入校园网,通过nat分化出网段 192.168.. 实验过程 主机A(windows)接入路由器(192.168.1.110),主机B(Ubuntu)接 ...

  2. 【二分图匹配】Plug It In!

    http://codeforces.com/gym/101873 F 先对原图跑一遍匈牙利得到原始最大匹配,再遍历每个出度>1的点,考虑若新加入点,能否找到增广路,若可行则答案对应增加 代码: ...

  3. Java 数组转字符

    public static String toString(int[] arr){ String temp = ""; for(int i = 0;i<arr.length; ...

  4. Struts2(七)

    以下内容是基于导入struts2-2.3.32.jar包来讲的 1.xml验证 Struts2提供了验证器,实现了通用的验证逻辑.例如: 非空验证器.长度验证器.日期验证器.email验证器等.具体定 ...

  5. PHP中大括号用法

    Php中"{}"大括号的用法总结 在PHP中,大括号“{}”可以起到如下作用: 1.将多个独立语句合并为一个复合语句,例如 if ... else ...中经常如此使用 2.在变量 ...

  6. Spring Cloud 架构 五大神兽的功能

    什么是微服务 微服务的概念源于2014年3月Martin Fowler所写的一篇文章“Microservices”. 微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调 ...

  7. 【Django】Django—Form两种解决表单数据无法动态刷新的方法

    一.无法动态更新数据的实例 1. 如下,数据库中创建了班级表和教师表,两张表的对应关系为“多对多” from django.db import models class Classes(models. ...

  8. bzoj4639 博士的选取器

    题意 给出一个长度为n的正整数序列,要求把它划分成若干个连续的区间,使得每个区间的数字之和都不超过给定的lim.最后的代价等于每个区间的最大值之和.求最小代价.n<=300000 分析 定义f[ ...

  9. CodeForces 860D Wizard's Tour

    题意 给出一张无向图,要求找出尽量多的长度为2的不同路径(边不可以重复使用,点可以重复使用) 分析 yzy:这是原题 http://www.lydsy.com/JudgeOnline/problem. ...

  10. web项目访问路径上为什么不能写上WebContent

    我们常常在WEB项目中要写很多的访问路径,比如说/good/target.jsp;目录结构中从来不会带有项目目录结构的WebContent?这到底的为什么呢? 我们知道WEB项目是放在容器上运行的,而 ...