2017北京国庆刷题Day6 afternoon
期望得分: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的更多相关文章
- 2017北京国庆刷题Day1 afternoon
期望得分:100+100+100=300 实际得分:100+100+100=300 T1 一道图论好题(graph) Time Limit:1000ms Memory Limit:128MB 题目 ...
- 2017北京国庆刷题Day5 afternoon
期望得分:100+60+100=260 实际得分:0+60+40=100 设图中有m个环,每个环有si条边,有k条边不在环中 ans= (2^s1 -2)*( 2^s2 -2)* (2^s3 -2)… ...
- 2017北京国庆刷题Day2 afternoon
期望得分:100+100+50=250 实际得分:100+70+50=220 T1 最大值(max) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一 ...
- 2017北京国庆刷题Day4 afternoon
期望得分:100+100+0=200 实际得分:5+0+0=5 每加入一个数,x的因数位置++ 注意:根号x枚举时,如果x是完全平方数,根号x会重复累计2次,要减去 考场上没减,5分 /(ㄒoㄒ)/~ ...
- 2017北京国庆刷题Day3 afternoon
期望得分:100+0+30=130 实际得分:100+36.5+0=136.5 T3 一个变量写混了,丢了30.. 模拟栈 #include<cstdio> #include<cst ...
- 2017北京国庆刷题Day7 afternoon
期望得分:100+30+100=230 实际得分:60+30+100=190 排序去重 固定右端点,左端点单调不减 考场上用了二分,没去重,60 #include<cstdio> #inc ...
- 2017北京国庆刷题Day6 morning
期望得分:100+100+20=220 实际得分:100+100+20=220 模拟栈 #include<cstdio> #include<cstring> using nam ...
- 2017北京国庆刷题Day7 morning
期望得分:100+0+100=200 实际得分:100+20+0=120 离散化搞搞 #include<cstdio> #include<iostream> #include& ...
- 2017北京国庆刷题Day3 morning
期望得分:100+60+0=160 实际得分:100+30+0=130 考场上用的哈希 #include<cstdio> #include<cstring> #include& ...
随机推荐
- Scrum立会报告+燃尽图(十月二十日总第十一次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2246 项目地址:https://git.coding.net/zhang ...
- asp.netcore mvc 权限拦截
1-背景介绍 需要做一个简单权限系统,基于 角色,用户,菜单 的模式 基于IActionFilter全局拦截,在内部跳转或者浏览器跳转的时候,拦截是成功的,当通过AJAX 请求的时候,页面就不会跳转 ...
- HDU 5206 Four Inages Strategy 水题
题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5206 bc(中文):http://bestcoder.hdu.edu.cn/contests ...
- swift - tabBar图片设置的一些注意点
图片大小尺寸 刚刚开始接触的话,从美工那边拿来的图标大小一般都是偏大的,就像这样: 在此建议,tabBar的图标大小可以是32*32,个人感觉效果不错 图片的颜色问题 如上图所示,该图标的期望颜色(也 ...
- Swift-setValuesForKeysWithDictionary
重写 setValuesForKeysWithDictionary 那么字典中可以有的字段在类中没有对应属性 class Person : NSObject { var age :Int = // 重 ...
- 浅谈 Sql Server 触发器
一.触发器概念 1.1.触发器特征 1.1.1.触发器是在对表进行增.删.改时,自动执行的存储过程.触发器常用于强制业务规则,它是一种高级约束,通过事件进行触发而被执行. ...
- bzoj3545-bzoj3551-Peaks
题意 给出一个图,边有边权,点有点权,每次询问一个点 \(x\) 只走边权小于等于 \(d\) 的边能到达的点中点权第 \(k\) 大. 强制在线,\(n\le 10^5,m,q\le 5\times ...
- 【bzoj3518】点组计数 欧拉函数(欧拉反演)
题目描述 平面上摆放着一个n*m的点阵(下图所示是一个3*4的点阵).Curimit想知道有多少三点组(a,b,c)满足以a,b,c三点共线.这里a,b,c是不同的3个点,其顺序无关紧要.(即(a,b ...
- VS中碰到的问题
1.调试的时候,语句已经注释掉了,但是在执行的时候还是运行了(或者某些变量值改变后,程序依然用的之前数据). 右键解决方案-->清理,然后重新生成.
- [一]SpringBoot 之 HelloWorld
(1)新建一个Maven Java工程 (2)在pom.xml文件中添加Spring BootMaven依赖 2.1在pom.xml中引入spring-boot-start-parent spring ...