博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
usaco 2017 US Open
阅读量:4334 次
发布时间:2019-06-07

本文共 4371 字,大约阅读时间需要 14 分钟。

来自FallDream的博客。未经允许,请勿转载,谢谢。

----------------------------------------------------

A:Modern Art

给定一个n*n的网格,有n*n个颜色,每种颜色按一定顺序覆盖了一个矩形。给定末状态,求有几种颜色可能是第一个填上去的。n<=1000

题解:二维查分+前缀和起来,然后就可以快速求得每个点被覆盖了多少次啦。复杂度n^2

#include
#include
#include
#include
using namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f;}int n,ans=0;int x1[1000005],x2[1000005],y1[1000005],y2[1000005];int f[1005][1005],s[1005][1005];bool b[1000005];int main(){ n=read(); for(int i=1;i<=n*n;i++)x2[i]=y2[i]=0,x1[i]=y1[i]=1004; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { int x=read();s[i][j]=x;if(!x)continue; if(!b[x])ans++,b[x]=1;x1[x]=min(x1[x],i);x2[x]=max(x2[x],i); y1[x]=min(y1[x],j);y2[x]=max(y2[x],j); } if(ans==1)return 0*printf("%d",n*n-1);ans=n*n; for(int i=1;i<=n*n;i++)if(b[i]) { f[x1[i]][y1[i]]++;f[++x2[i]][y1[i]]--; f[x1[i]][++y2[i]]--;f[x2[i]][y2[i]]++; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)f[i][j]+=f[i-1][j]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)f[i][j]+=f[i][j-1]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(s[i][j]&&b[s[i][j]]) { int x=s[i][j]; if(f[i][j]>1) b[x]=0,ans--; } cout<

B.Switch Grass

给定一个n个点m条边的图,每个点有一个颜色,边有边权。q个操作,每次修改一个点的颜色,询问连接的两个点颜色不同的权值最小的边的权值。n,m,q<=200000

先提供一种玄学做法,最坏n^2,但是usaco数据弱,也A了。

我们先把边按照权值排序,然后用fail[i]表示前i条边都不合法的情况下,下一条颜色可能不同的边是哪条。这个可以通过并查集处理出来。然后记录每个点最先出现的边的编号。每次修改,看一下修改的点的编号是否比答案小,如果小,那条边一定成为答案。如果不小的话,看一下是否把现在的答案这条边改成了相同的颜色,如果相同就沿着fail指针找到第一个不同的点,复杂度最坏n^2,但是由于数据弱,并且很多操作是O(1)的,所以卡过了,最久的点只跑了1074ms。

#include
#include
#include
#include
#define MAXN 200000using namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f;}int n,m,k,q,ans;int fail[MAXN+5];int s[MAXN+5],col[MAXN+5],first[MAXN+5];struct edge{ int to,from,w,num;}e[MAXN+5];bool cmp(edge x,edge y){
return x.w

官方题解:我们可以发现对答案有贡献的边只会在最小生成树上,所以先跑出mst然后给他定一个根。然后我们对每一个点,对它儿子所有可能的颜色都建一个堆。 

这样修改一个点只要从它父亲那里删掉一个点然后重新扔一个进去就可以了。这样每个点的答案就是和它颜色不同的堆的最小值,之后我们再对整体建一个堆,把每个

堆的答案扔进去,就可以啦。

我觉得堆有点难受,所以对每个节点建了个平衡树,还作死写了splay,之后再用线段树搞起来,差点T了.....复杂度nlogn 跑得比暴力还慢...

#include
#include
#include
#include
#define MAXN 1500000#define MAXL 200000#define N 262144#define INF 2000000000using namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f;}int n,m,qq,cnt=0;int fa[MAXN+5],fat[MAXL+5],c[MAXN+5][2],s[MAXN+5],head[MAXL+5],ans[MAXN+5];int rt[MAXL+5],col[MAXN+5],num[MAXN+5],mx[MAXN+5],size[MAXN+5],id[MAXN+5],upx[MAXN+5];int T[N*2+5];struct edge{ int from,to,w;}e[200005];struct edge_type_2{ int next,to,w;}e2[400005];bool cmp(edge x,edge y){
return x.w
>=1;x;x>>=1)T[x]=min(T[x<<1],T[x<<1|1]);}inline void update(int x){ if(!x)return; int l=c[x][0],r=c[x][1]; size[x]=size[l]+size[r]+1; mx[x]=min(mx[l],min(mx[r],num[x]));}void rotate(int x,int&k){ int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; if(y==k)k=x; else c[z][c[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; update(y);update(x);}void splay(int x,int&k){ // cout<<"splay"<
<
id[x])],rk,x,w,fid); else if(s[x]>rk)ins(c[x][0],rk,x,w,fid); else ins(c[x][1],rk,x,w,fid); update(x);}void dfs(int x,int f){ fat[x]=f; for(int i=head[x];i;i=e2[i].next) if(e2[i].to!=f) {upx[e2[i].to]=e2[i].w;ins(rt[x],col[e2[i].to],0,e2[i].w,e2[i].to);dfs(e2[i].to,x);}}int find(int x,int rk,int fid){ if(s[x]==rk) { if(id[x]==fid)return x;return find(c[x][(fid>id[x])],rk,fid);} if(s[x]>rk)return find(c[x][0],rk,fid); else return find(c[x][1],rk,fid);}int get(int x,int rk){ // cout<<"get"<
<<" "<
<
0?q:x; else if(s[x]

 C沙比提不想做

转载于:https://www.cnblogs.com/FallDream/p/usaco2017usopen.html

你可能感兴趣的文章
laravel连接sql server 2008
查看>>
Ubuntu菜鸟入门(五)—— 一些编程相关工具
查看>>
valgrind检测linux程序内存泄露
查看>>
Hadoop以及组件介绍
查看>>
1020 Tree Traversals (25)(25 point(s))
查看>>
第一次作业
查看>>
“==”运算符与equals()
查看>>
单工、半双工和全双工的定义
查看>>
Hdu【线段树】基础题.cpp
查看>>
时钟系统
查看>>
BiTree
查看>>
5个基于HTML5的加载动画推荐
查看>>
水平权限漏洞的修复方案
查看>>
静态链接与动态链接的区别
查看>>
Android 关于悬浮窗权限的问题
查看>>
如何使用mysql
查看>>
linux下wc命令详解
查看>>
敏捷开发中软件测试团队的职责和产出是什么?
查看>>
在mvc3中使用ffmpeg对上传视频进行截图和转换格式
查看>>
python的字符串内建函数
查看>>