这个普及比普及水多了。(雾)
题目水到我 9:44 写完又对拍到 11:00 然后发现自己差劲的代码能力一遍AK?(并没有)
所以总结就不写了
考场本来有 Sublime ,结果想配一下自动补全的时候 C++ 包莫名其妙没了,于是只能当记事本用。
本来用的 fread
快读,但是发现数据后都没有回车 fread
会双倍末尾,于是换成了 getchar
。
这场比赛因为我清奇的脑回路变成了并查集专题。
T1 map
模拟水题。
#include<cstdio>
using namespace std;
int n,a[2010][2010],r[2010],c[2010],x=1,y=1,ox,oy;
template<typename T>void read(T &x){
char c=getchar();
for(;c<33;c=getchar());
for(x=0;47<c&&c<58;x=(x<<3)+(x<<1)+(c^48),c=getchar());
}
int main(){
freopen("map.in","r",stdin);
freopen("map.out","w",stdout);
read(n);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
read(a[i][j]);
}
}
for(int i=2;i<n;++i){
r[i]=a[n][1];
c[i]=a[1][n];
for(int j=2;j<=n;++j){
r[i]^=a[i][j]^a[n][j];
c[i]^=a[j][i]^a[j][n];
}
}
for(int i=2;i<n;++i){
if(r[i]!=a[i][1]){
x=i;
++ox;
}
if(c[i]!=a[1][i]){
y=i;
++oy;
}
}
if(a[1][1]==1){
printf("1 1"); //然现在发现并不需要
}else{
printf("%d %d",ox>1?n:x,oy>1?n:y);
}
fclose(stdin);
fclose(stdout);
return(0);
}
T2 water
全场最有质量的题……?
是 water !
暗示我们比赛很水
然后身边一群人写 (nlog ^2n) ,然后 (nlog n) 的方法也很神奇,甚至 Splay 、甚至 ST 表、甚至权值线段树……甚至再套二分……?反正我写的并查集。
首先如果水越加越高,那么就会不断的使有水的区间变大。
所以直接对询问由小到大排序,记录区间的左右端点,暴力拓展,用并查集合并即可。
随便写写跑得飞快,然后写完 T4 把 T4 的 sz 数组 copy 了过来搞了个按秩合并。
#include<cstdio>
#include<algorithm>
#define N 200010
using namespace std;
int n,m,c[N],sz[N];
long long ans[N],a[N],s[N],l[N],r[N];
struct ques{
int x,y,num;
}q[N];
template<typename T>void read(T &x){
char c=getchar();
for(;c<33;c=getchar());
for(x=0;47<c&&c<58;x=(x<<3)+(x<<1)+(c^48),c=getchar());
}
bool cmp(ques a,ques b){
return(a.y<b.y);
}
int root(int x){
if(c[x]){
sz[c[x]]+=sz[x];
sz[x]=0;
return(c[x]=root(c[x]));
}
return(x);
}
int uni(int x,int y){
x=root(x);y=root(y);
if(sz[x]<sz[y]){
swap(x,y);
}
if(x!=y){
c[y]=x;
sz[x]+=sz[y];
sz[y]=0;
l[x]=min(l[x],l[y]);
r[x]=max(r[x],r[y]);
}
return(x);
}
int main(){
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
read(n);read(m);
for(int i=1;i<=n;++i){
read(a[i]);
s[i]=s[i-1]+a[i];
l[i]=r[i]=i;
sz[i]=1;
}
for(int i=1;i<=m;++i){
read(q[i].x);read(q[i].y);q[i].num=i;
}
sort(q+1,q+1+m,cmp);
for(int i=1;i<=m;++i){
q[i].x=root(q[i].x);
for(;a[l[q[i].x]-1]<q[i].y&&l[q[i].x]>1;q[i].x=uni(l[q[i].x]-1,q[i].x));
for(;a[r[q[i].x]+1]<q[i].y&&r[q[i].x]<n;q[i].x=uni(r[q[i].x]+1,q[i].x));
ans[q[i].num]=(r[q[i].x]-l[q[i].x]+1)*q[i].y-s[r[q[i].x]]+s[l[q[i].x]-1];
}
for(int i=1;i<=m;++i){
printf("%lld
",ans[i]);
}
fclose(stdin);
fclose(stdout);
return(0);
}
T3 match
甚至比 T1 好写,贪心显然。
然后死于数组没开大。
#include<cstdio>
#include<algorithm>
using namespace std;
int n,l,r,a[100010],ans; //我谔谔极了
//int n,l,r,a[1000010],ans;
template<typename T>void read(T &x){
char c=getchar();
for(;c<33;c=getchar());
for(x=0;47<c&&c<58;x=(x<<3)+(x<<1)+(c^48),c=getchar());
}
int main(){
freopen("match.in","r",stdin);
freopen("match.out","w",stdout);
read(n);read(l);read(r);
for(int i=1;i<=n;++i){
read(a[i]);
}
sort(a+1,a+n+1);
for(int x=1,y=n;x<=y;){
if(x==y){
++ans;
break;
}else if(a[x]+a[y]<l){
++x;
++ans;
}else if(a[x]+a[y]>r){
--y;
++ans;
}else{
++x;
--y;
}
}
printf("%d",ans);
fclose(stdin);
fclose(stdout);
return(0);
}
T4 travel
考场上屡次打成 tarvel 了解一下?
首先就是,这道题是原题: USACO2018JanGold P1. MooTube 。
除了多了若干条边以外并没有任何区别。
离线排序并查集。
就跟T2一样
#include<cstdio>
#include<algorithm>
#define N 200010
using namespace std;
int n,m,k,s[N],sz[N],ans[N];
struct edge{
int x,y,c;
}e[N<<3],q[N<<3];
template<typename T>void read(T &x){
char c=getchar();
for(;c<33;c=getchar());
for(x=0;47<c&&c<58;x=(x<<3)+(x<<1)+(c^48),c=getchar());
}
bool cmp(edge a,edge b){
return(a.c<b.c);
}
void pushup(int x){
sz[s[x]]+=sz[x];
sz[x]=0;
}
int root(int x){
if(s[x]){
pushup(x);
return(s[x]=root(s[x]));
}
return(x);
}
int uni(int x,int y){
x=root(x);y=root(y);
if(sz[x]<sz[y]){
swap(x,y);
}
if(x!=y){
s[y]=x;
pushup(y);
}
return(x);
}
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
read(n);read(m);
for(int i=1;i<=n;++i){
sz[i]=1;
}
for(int i=0;i<m;++i){
read(e[i].x);read(e[i].y);read(e[i].c);
}
read(k);
for(int i=0;i<k;++i){
read(q[i].x);read(q[i].c);q[i].y=i;
}
sort(e,e+m,cmp);
sort(q,q+k,cmp);
for(int i=0,j=0;i<k;++i){
for(;j<=m&&e[j].c<=q[i].c;uni(e[j].x,e[j].y),++j);
ans[q[i].y]=sz[root(q[i].x)];
}
for(int i=0;i<k;++i){
printf("%d
",ans[i]);
}
fclose(stdin);
fclose(stdout);
return(0);
}