早上睡到 7:10 分才想起今天有 GDKOI ,赶紧去买了一个面包赶去机房
发现隔壁的大奆都过来了。比赛时由于昨晚一直没睡好,打了两个小时的哈欠
T1 :暴力模拟
根据 (r) 和 (c) 的错误个数有九种情况,
=0 | =1 | >1 | |
---|---|---|---|
=0 | |||
=1 | |||
>1 |
分类讨论即可
T2 :RMQ 瞎弄
对与一个询问,在左右分别找到一个最近的比他高的点
可以用 RMQ + 二分,也可以离线
本蒟蒻用了前者,复杂度(O(nlog n+qlog n))
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200005;
int x[N],n,T,p[35]={1},lg[N],f[N][35],vl;
LL sm[N],res;
inline int RMQ(int l,int r) {
register int k=lg[r-l+1];
return max(f[l][k],f[r-p[k]+1][k]);
}
int Left(int l,int r) {
register int mid;
while(l<r) {
mid=l+r>>1;
if(RMQ(mid+1,r)>=vl)l=mid+1;
else r=mid;
} return l;
}
int Right(int l,int r) {
register int mid;
while(l<r) {
mid=l+r>>1;
if(RMQ(l,mid)>=vl)r=mid;
else l=mid+1;
} return l;
}
int main() {
for(int i=1;i<31;i++)p[i]=p[i-1]<<1;
scanf("%d%d",&n,&T);
for(int i=1;i<=n;i++)scanf("%d",&x[i]),sm[i]=1LL*x[i]+sm[i-1],f[i][0]=x[i];
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
++n,x[0]=x[n]=f[n][0]=f[0][0]=2000000000;
for(int j=1;j<31;j++)
for(int i=0;i+p[j-1]-1<=n;i++)
f[i][j]=max(f[i][j-1],f[i+p[j-1]][j-1]);
for(int p,u,v;T--;) {
scanf("%d%d",&p,&vl);
u=Left(0,p-1),v=Right(p+1,n+1);
res=1LL*(v-u-1)*vl-sm[v-1]+sm[u];
printf("%lld
",res);
}
}
T3 贪心
真的比第一题还人口普查,直接排序贪心,用两个指针
- a[i]+a[j]>r ,直接删 j
- a[i]+a[j]<l ,直接删 i
- 匹配成功
T4 离线
贪心思想:钱都去买通票最后花费不会变多
离线,先将边按边权递增排序,再将查询按上限排序
把边权小于上限的边都删掉,并把删掉的边两点所在联通块合并
最后答案就是起点所在联通块点个数
#include<bits/stdc++.h>
using namespace std;
const int N=400005;
int n,m,T,ans[N],fa[N],sm[N],x[N],y[N],z[N],u[N],v[N],w[N];
void Sort(int l,int r) {
int i=l,j=r,mid=w[l+r>>1];
while(i<=j) {
while(w[i]<mid)++i;
while(w[j]>mid)--j;
if(i<=j) {
swap(u[i],u[j]);
swap(v[i],v[j]);
swap(w[i],w[j]);
i++,j--;
}
}
if(i<r)Sort(i,r);
if(j>l)Sort(l,j);
}
inline int Fnd(int x) {
return fa[x]^x?fa[x]=Fnd(fa[x]):x;
}
void Kp(int l,int r) {
int i=l,j=r,mid=y[l+r>>1];
while(i<=j) {
while(y[i]<mid)++i;
while(y[j]>mid)--j;
if(i<=j) {
swap(x[i],x[j]);
swap(y[i],y[j]);
swap(z[i],z[j]);
i++,j--;
}
}
if(i<r)Kp(i,r);
if(j>l)Kp(l,j);
}
int main() {
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&u[i],&v[i],&w[i]);
for(int i=1;i<=m;i++)fa[i]=i,sm[i]=1;
if(m>1)Sort(1,m);
scanf("%d",&T);
for(int i=1;i<=T;i++)scanf("%d%d",&x[i],&y[i]),z[i]=i;
if(T>1)Kp(1,T);
for(int i=1,j=1,p,q;i<=T;i++) {
while(j<=m && w[j]<=y[i]) {
p=Fnd(u[j]),q=Fnd(v[j]),++j;
if(p^q)fa[q]=p,sm[p]+=sm[q];
} ans[z[i]]=sm[Fnd(x[i])];
}
for(int i=1;i<=T;i++)printf("%d
",ans[i]);
}
End
今天的第一题情况没考虑全,要细心
T2 和 T3 发挥不错, T4 这种动态题可以想想离线