POI2010题解

我也不知道我为什么就开始刷POI了

有些题目咕掉了所以不完整(我都不知道POI到底有多少题)

[BZOJ2079][Poi2010]Guilds

(貌似bz跟洛谷上的不是一个题?)

并查集判孤立点就行了。

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 2e5+5;
int n,m,fa[N],sz[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main(){
n=gi();m=gi();
for (int i=1;i<=n;++i) fa[i]=i,sz[i]=1;
for (int i=1;i<=m;++i){
int u=gi(),v=gi();
u=find(u);v=find(v);if (sz[u]<sz[v]) swap(u,v);
if (u^v) sz[u]+=sz[v],fa[v]=u;
}
for (int i=1;i<=n;++i) if (sz[find(i)]==1) return puts("NIE"),0;
return puts("TAK"),0;
}

[BZOJ2080][Poi2010]Railway

这个题是这的神仙。膜了Claris老师的题解才做出来的。

考虑什么时候两个点不能进同一个栈:当且仅当\(i<j,a_i<a_j\),且存在一个\(k>j\)使得\(a_k<a_i\)时,\(i,j\)不能在同一个栈里。这样的\(i,j\)点对连边然后跑二分图染色就好了。但是显然暴力建图是承受不了的。

记\(b_i\)表示序列的后缀最小值,即\(b_i=\min_{j=i}^na_j\),那么上述条件就变成了\(b_j<a_i<a_j\)。

再记一个\(c_i\)表示\(\max\{j|b_j<i\}\)。

开两棵线段树,一棵以原下标为下标维护\(a\)的最大值,一棵以\(a\)值为下标维护原下标的最小值。

可以发现,一个点\(i\)与之相连的是下标在\([i+1,c_{a_i}]\)中\(a\)值大于\(a_i\)的数,以及\(a\)值在\([b_i+1,a_i-1]\)中的所有下标小于\(i\)的数,线段树区间查询,查完就把那个点删掉,就可以走遍整棵\(dfs\)树的树边,构造出一组颜色序列。

然后已知了颜色就再判一下非树边会不会无解就行了。也就是对于每个\(j\)来说,看看有没有与其同色的满足\(b_j<a_i<a_j\)的\(i\)即可。

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e5+5;
int n,a[N],f[N],b[N],c[N],col[N],bit[3][N];
struct segment_tree{
int t[N<<2],ty;
int cal(int i,int j){
if (!i||!j) return i|j;
return ty?(i<j?i:j):(a[i]>a[j]?i:j);
}
void build(int x,int l,int r){
if (l==r) {t[x]=ty?f[l]:l;return;}
int mid=l+r>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
t[x]=cal(t[x<<1],t[x<<1|1]);
}
void modify(int x,int l,int r,int p){
if (l==r) {t[x]=0;return;}
int mid=l+r>>1;
if (p<=mid) modify(x<<1,l,mid,p);
else modify(x<<1|1,mid+1,r,p);
t[x]=cal(t[x<<1],t[x<<1|1]);
}
int query(int x,int l,int r,int ql,int qr){
if (ql>qr) return 0;if (l>=ql&&r<=qr) return t[x];
int mid=l+r>>1;
if (qr<=mid) return query(x<<1,l,mid,ql,qr);
if (ql>mid) return query(x<<1|1,mid+1,r,ql,qr);
return cal(query(x<<1,l,mid,ql,qr),query(x<<1|1,mid+1,r,ql,qr));
}
}T1,T2;
void dfs(int x,int z){
T1.modify(1,1,n,x);T2.modify(1,1,n,a[x]);col[x]=z;
while (233){
int y=T1.query(1,1,n,x+1,c[a[x]]);
if (!y||a[y]<a[x]) break;dfs(y,z^3);
}
while (666){
int y=T2.query(1,1,n,b[x]+1,a[x]-1);
if (!y||y>x) break;dfs(y,z^3);
}
}
void mdf(int j,int k){while(k<=n)++bit[j][k],k+=k&-k;}
int qry(int j,int k){int s=0;while(k)s+=bit[j][k],k^=k&-k;return s;}
int main(){
n=gi();
for (int i=1;i<=n;++i) a[i]=gi(),f[a[i]]=i;
b[n+1]=1e9;
for (int i=n;i;--i) b[i]=min(b[i+1],a[i]);
for (int i=1,j=0;i<=n;++i){
while (j<=n&&b[j+1]<i) ++j;
c[i]=j;
}
T2.ty=1;T1.build(1,1,n);T2.build(1,1,n);
for (int i=1;i<=n;++i) if (!col[i]) dfs(i,1);
for (int i=1;i<=n;++i){
if (qry(col[i],a[i]-1)-qry(col[i],b[i])>0) return puts("NIE"),0;
mdf(col[i],a[i]);
}
puts("TAK");
for (int i=1;i<=n;++i) printf("%d ",col[i]);
puts("");return 0;
}

[BZOJ2081][Poi2010]Beads

\(Hash\)+去重即可。复杂度\(O(n\log^2n)\) 。

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
#define ull unsigned long long
const int N = 2e5+5;
const ull base = 20020415;
int n,a[N],ans,len,q[N];ull pw[N],h1[N],h2[N],tmp[N];
ull cal(int l,int r){
ull s1=h1[r]-h1[l-1]*pw[r-l+1];
ull s2=h2[l]-h2[r+1]*pw[r-l+1];
return min(s1,s2);
}
int main(){
n=gi();
for (int i=1;i<=n;++i) a[i]=gi();
for (int i=1;i<=n;++i) h1[i]=h1[i-1]*base+a[i];
for (int i=n;i>=1;--i) h2[i]=h2[i+1]*base+a[i];
for (int i=pw[0]=1;i<=n;++i) pw[i]=pw[i-1]*base;
for (int i=1;i<=n;++i){
int res=0;
for (int j=1;j+i-1<=n;j+=i) tmp[++res]=cal(j,j+i-1);
sort(tmp+1,tmp+res+1);
res=unique(tmp+1,tmp+res+1)-tmp-1;
if (res>ans) ans=res,q[len=1]=i;
else if (res==ans) q[++len]=i;
}
printf("%d %d\n",ans,len);
for (int i=1;i<=len;++i) printf("%d ",q[i]);
return puts(""),0;
}

[BZOJ2082][Poi2010]Divine divisor

\(\mbox{Pollard_Rho}\)质因数分解,取次数最高的那个质因子。第二问答案一定是\(2^k-1\)的形式,随便写个高精,只要支持乘\(2\)就行了。

发现了一种比之前写的快三十倍的新写法,可以通过洛谷模板。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
ll gi(){
ll x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
ll mul(ll x,ll y,ll mod){
return (x*y-(ll)((long double)x/mod*y+0.5)*mod+mod)%mod;
}
ll fastpow(ll x,ll y,ll mod){
ll res=1;
while (y) {if (y&1) res=mul(res,x,mod);x=mul(x,x,mod);y>>=1;}
return res;
}
ll f[]={2,3,5,7,11,13,17,19,23,29};
bool MR(ll p){
for (int i=0;i<10;++i){
if (p<=f[i]) break;
if (fastpow(f[i],p-1,p)!=1) return false;
ll pp=p-1;
while (~pp&1){
pp>>=1;ll y=fastpow(f[i],pp,p);
if (mul(y,y,p)==1&&y!=1&&y!=p-1) return false;
}
}
return true;
}
ll PR(ll n){
ll x=0,y=0,t=1,q=1,a=1+rand()%(n-1);
for (int k=2;true;k<<=1,y=x,q=1){
for (int i=1;i<k;++i){
x=(mul(x,x,n)+a)%n;
q=mul(q,abs(x-y),n);
if (!(i&127)){
t=__gcd(q,n);
if (t>1) break;
}
}
if (t>1||(t=__gcd(q,n))>1) break;
}
if (t==n) t=1;return t;
}
ll a[50000],b[50000];int len,c[50000],cnt,ans;
void fact(ll n){
if (n==1) return;
if (MR(n)) {a[++len]=n;return;}
ll p=n;while (p==n) p=PR(p);
fact(p);fact(n/p);
}
const int N = 1000000000;
struct bigint{
int a[5000],w;
bigint(){a[w=0]=1;}
void mul(){
for (int i=0;i<=w;++i) a[i]<<=1;
for (int i=0;i<=w;++i) a[i+1]+=a[i]/N,a[i]%=N;
while (a[w+1]) ++w,a[w+1]+=a[w]/N,a[w]%=N;
}
void print(){
printf("%d",a[w]);
for (int i=w-1;~i;--i) printf("%09d",a[i]);
puts("");
}
}Ans;
int main(){
srand(20020415);
int m=gi();
while (m--) fact(gi());
sort(a+1,a+len+1);
for (int i=1;i<=len;++i){
if (i==1||a[i]>a[i-1]) b[++cnt]=a[i];
++c[cnt];
}
for (int i=1;i<=cnt;++i) ans=max(ans,c[i]);
for (int i=1;i<=cnt;++i) if (c[i]==ans) Ans.mul();
printf("%d\n",ans);--Ans.a[0];Ans.print();
return 0;
}

[BZOJ2083][Poi2010]Intelligence test

\(vector\)上二分。

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
vector<int>v[1000005];
vector<int>::iterator it;
int main(){
int m=gi();
for (int i=1;i<=m;++i) v[gi()].push_back(i);
int n=gi();while (n--){
int l=gi(),lst=0,ans=1;
for (int i=1;i<=l;++i){
int x=gi();
it=upper_bound(v[x].begin(),v[x].end(),lst);
if (it==v[x].end()) ans=0;
else lst=*it;
}
puts(ans?"TAK":"NIE");
}
return 0;
}

[BZOJ2084][Poi2010]Antisymmetry

一个合法串一定满足:后半段\(01\)翻转以后是回文。

把原串复制一份\(01\)翻转,然后隔一个位置插一个插进原串。这样合法串就变成了一个偶长度的回文串。

把\(Manacher\)魔改一下就可以做只有偶长度的回文串啦。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e6+5;
int n,s[N],p[N],mx,id;char str[N];long long ans;
int main(){
scanf("%d%s",&n,str);
for (int i=0;i<n;++i) s[i<<1]=str[i]-'0',s[i<<1|1]=s[i<<1]^1;
n<<=1;
for (int i=1;i<n;++i){
p[i]=mx>i?min(p[2*id-i],mx-i):0;
while (i+p[i]<n&&i-p[i]-1>=0&&s[i+p[i]]==s[i-p[i]-1]) ++p[i];
ans+=p[i]>>1;if (i+p[i]>mx) mx=i+p[i],id=i;
}
printf("%lld\n",ans);
return 0;
}

[BZOJ2086][Poi2010]Blocks

就是要找一个区间使得平均数\(\ge k\)。

把每个数减\(k\)再记前缀和,相当于求两个位置,满足前面小于等于后面,要求下标差最大。找出所有的前缀最小值,从后往前扫一遍即可。

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
#define ll long long
const int N = 1e6+5;
int n,m,a[N],q[N],top,ans;long long sum[N],k;
int main(){
n=gi();m=gi();
for (int i=1;i<=n;++i) a[i]=gi();
while (m--){
k=gi();top=ans=0;
for (int i=1;i<=n;++i) sum[i]=sum[i-1]+a[i]-k;
for (int i=1;i<=n;++i) if (sum[i]<sum[q[top]]) q[++top]=i;
for (int i=n;i;--i){
while (top&&sum[i]>=sum[q[top-1]]) --top;
ans=max(ans,i-q[top]);
}
printf("%d ",ans);
}
puts("");return 0;
}

[BZOJ2087][Poi2010]Sheep

先求一下凸包上任意两点之间连边后两侧的羊数是否都是偶数,然后直接\(O(n^3)\)区间\(dp\)。

注意一下一条对角线恰好经过某一只羊的情况(这样的边不能连)。

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 605;
struct node{
int x,y;
node operator - (const node &b) const
{return (node){x-b.x,y-b.y};}
int operator * (const node &b) const
{return x*b.y-y*b.x;}
}a[N],b[N<<6],now;
bool cmp(node a,node b){
return (a-now)*(b-now)<0;
}
int n,m,mod,f[N][N],g[N][N];
int main(){
n=gi();m=gi();mod=gi();
for (int i=1;i<=n;++i) a[i]=(node){gi(),gi()};
for (int i=1;i<=m;++i) b[i]=(node){gi(),gi()};
now=a[1];sort(a+2,a+n+1,cmp);
for (int i=1;i<=n;++i){
now=a[i];sort(b+1,b+m+1,cmp);
for (int j=i+1,k=0;j<=n;++j){
while (k<m&&(b[k+1]-now)*(a[j]-now)<0) ++k;
if ((k&1)||(k<m&&(b[k+1]-now)*(a[j]-now)==0)) continue;
f[i][j]=1;
}
}
for (int i=1;i<n;++i) g[i][i+1]=1;
for (int l=3;l<=n;++l)
for (int i=1,j=i+l-1;j<=n;++i,++j)
for (int k=i+1;k<j;++k)
if (f[i][k]&&f[k][j])
(g[i][j]+=g[i][k]*g[k][j])%=mod;
printf("%d\n",g[1][n]);return 0;
}

[BZOJ2088][Poi2010]Teleportation

可以发现最终的图是一个分层图,共四层,每层内连成一个完全图,相邻两层之间两两连边。其中与\(1\)相连的点在第一层,与\(2\)相连的点在第四层。

很显然没有跟\(1,2\)连边的点不会放在第一层或是最后一层,因为一定不更优,不如放在中间两层。

与 与\(1\)相邻的点 相邻的点在第二层,与 与\(2\)相邻的点 相邻的点在第三层。

其余的点是放在第二层还是放第三层呢?只需要比较第一层与第四层的大小即可。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 2e6+5;
int n,m,to[N],nxt[N],head[N],cnt,vis[N],s[6];
long long ans;
int main(){
n=gi();m=gi();vis[1]=vis[2]=-1;
for (int i=1;i<=m;++i){
int u=gi(),v=gi();
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;
}
for (int e=head[1];e;e=nxt[e]) vis[to[e]]=1,++s[1];
for (int e=head[2];e;e=nxt[e]) vis[to[e]]=4,++s[4];
for (int i=3;i<=n;++i)
if (vis[i]==1)
for (int e=head[i];e;e=nxt[e])
if (!vis[to[e]]) vis[to[e]]=2,++s[2];
for (int i=3;i<=n;++i)
if (vis[i]==4)
for (int e=head[i];e;e=nxt[e])
if (!vis[to[e]]) vis[to[e]]=3,++s[3];
for (int i=3;i<=n;++i) if (!vis[i]) ++s[s[1]>s[4]?2:3];
s[0]=s[5]=1;
for (int i=0;i<=4;++i) ans+=1ll*s[i]*s[i+1];
for (int i=1;i<=4;++i) ans+=1ll*s[i]*(s[i]-1)>>1;
printf("%lld\n",ans-m);return 0;
}

[BZOJ2090][Poi2010]Monotonicity

(2089是弱化版)

设\(f_i\)表示\(a_i\)作为序列的末尾的最长长度。考虑把\(f_i\)转移出去,这样下一步的符号也就确定了。拿两棵线段树分别维护一下就行了。

(洛谷上需要输出方案)

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e6+5;
int n,m,a[N],b[N],las[N],f[N],pre[N],ans,S[N],top;char s[10];
int Max(int i,int j){return f[i]>f[j]?i:j;}
struct segment_tree{
int t[N<<2];
void modify(int x,int l,int r,int p,int v){
t[x]=Max(t[x],v);if (l==r) return;int mid=l+r>>1;
if (p<=mid) modify(x<<1,l,mid,p,v);
else modify(x<<1|1,mid+1,r,p,v);
}
int query(int x,int l,int r,int ql,int qr){
if (ql>qr) return 0;if (l>=ql&&r<=qr) return t[x];
int mid=l+r>>1,s=0;
if (ql<=mid) s=Max(s,query(x<<1,l,mid,ql,qr));
if (qr>mid) s=Max(s,query(x<<1|1,mid+1,r,ql,qr));
return s;
}
}T1,T2;
int main(){
n=gi();m=gi();
for (int i=1;i<=n;++i) a[i]=gi();
for (int i=1;i<=m;++i) scanf("%s",s),b[i]=s[0]=='='?2:s[0]=='>';
for (int i=1;i<=n;++i){
pre[i]=Max(las[a[i]],Max(T1.query(1,1,N,1,a[i]-1),T2.query(1,1,N,a[i]+1,N)));
f[i]=f[pre[i]]+1;ans=Max(ans,i);int op=b[(f[i]-1)%m+1];
if (!op) T1.modify(1,1,N,a[i],i);
else if (op&1) T2.modify(1,1,N,a[i],i);
else las[a[i]]=i;
}
printf("%d\n",f[ans]);
for (int i=ans;i;i=pre[i]) S[++top]=i;
for (int i=top;i;--i) printf("%d ",a[S[i]]);puts("");
return 0;
}

[BZOJ2091][Poi2010]The Minima Game

很显然每次选的都会是最大的若干个数不然不可能更优。

所以就可以\(dp\)了。设\(f_i\)表示前\(i\)小被选完,先手比后手多赢多少。转移\(f_i=\max_{j<i}a_{j+1}-f_j\)。

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
#define ll long long
const int N = 1e6+5;
int n,a[N];ll f[N],s;
int main(){
n=gi();
for (int i=1;i<=n;++i) a[i]=gi();
sort(a+1,a+n+1);s=a[1];
for (int i=1;i<=n;++i) f[i]=s,s=max(s,a[i+1]-f[i]);
printf("%lld\n",f[n]);return 0;
}

[BZOJ2093][Poi2010]Frog

先线性处理出每个位置跳一次跳到的位置,然后相当于要求这个置换的\(m\)次方。倍增数组开不下,可以采用快速幂的写法,空间复杂度\(O(n)\)。

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
ll gi(){
ll x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e6+5;
int n,k,S[N],T[N],tmp[N];ll m,a[N];
void mul(int *f,int *g){
for (int i=1;i<=n;++i) tmp[i]=g[f[i]];
for (int i=1;i<=n;++i) f[i]=tmp[i];
}
int main(){
n=gi();k=gi();m=gi();
for (int i=1;i<=n;++i) a[i]=gi();
for (int i=1,l=1,r=min(k+1,n);i<=n;++i){
while (r<n&&a[r+1]-a[i]<a[i]-a[l]) ++l,++r;
S[i]=i;T[i]=a[r]-a[i]>a[i]-a[l]?r:l;
}
while (m) {if (m&1) mul(S,T);mul(T,T);m>>=1;}
for (int i=1;i<=n;++i) printf("%d ",S[i]);
puts("");return 0;
}

[BZOJ2095][Poi2010]Bridges

先判无解,有奇度点当然就无解。

对于每条边先随便定向,假设是\(u \to v\),然后再考虑反悔。反悔会使\(u\)的度数\(+2\)而\(v\)的度数\(-2\)。而每个点都要满足度数为\(0\),所以从源汇连一些边不足一下,判补的这些边能不能流满。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 2005;
struct edge{int to,nxt,w;}a[N<<3];
int n,m,L,R,u[N],v[N],x[N],y[N],du[N],tot,head[N],cnt,S,T,dep[N],cur[N];
queue<int>Q;
void link(int u,int v,int w){
a[++cnt]=(edge){v,head[u],w};head[u]=cnt;
a[++cnt]=(edge){u,head[v],0};head[v]=cnt;
}
bool bfs(){
memset(dep,0,sizeof(dep));
dep[S]=1;Q.push(S);
while (!Q.empty()){
int u=Q.front();Q.pop();
for (int e=head[u];e;e=a[e].nxt)
if (a[e].w&&!dep[a[e].to])
dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
}
return dep[T];
}
int dfs(int u,int f){
if (u==T) return f;int res=0;
for (int &e=cur[u];e;e=a[e].nxt)
if (a[e].w&&dep[a[e].to]==dep[u]+1){
int d=dfs(a[e].to,min(a[e].w,f));
a[e].w-=d;a[e^1].w+=d;f-=d;res+=d;
if (!f) break;
}
if (!res) dep[u]=0;return res;
}
int dinic(){
int res=0;
while (bfs()){
for (int i=1;i<=T;++i) cur[i]=head[i];
res+=dfs(S,1000000000);
}
return res;
}
bool check(int mid){
memset(head,0,sizeof(head));cnt=1;
for (int i=1;i<=m;++i)
if (y[i]<=mid) link(u[i],v[i],1);
for (int i=1;i<=n;++i){
if (du[i]>0) link(S,i,du[i]>>1);
if (du[i]<0) link(i,T,-du[i]>>1);
}
return dinic()==tot;
}
int main(){
n=gi();m=gi();S=n+1;T=S+1;
for (int i=1;i<=m;++i){
u[i]=gi();v[i]=gi();x[i]=gi();y[i]=gi();
if (x[i]>y[i]) swap(u[i],v[i]),swap(x[i],y[i]);
L=max(L,x[i]);R=max(R,y[i]);
++du[u[i]];--du[v[i]];
}
int fg=1;
for (int i=1;i<=n;++i) if (du[i]&1) fg=0;
if (!fg) return puts("NIE"),0;
for (int i=1;i<=n;++i) if (du[i]>0) tot+=du[i]>>1;
while (L<R){
int mid=L+R>>1;
if (check(mid)) R=mid;
else L=mid+1;
}
printf("%d\n",R);return 0;
}

[BZOJ2096][Poi2010]Pilots

维护两个单调队列,就行了。

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 3e6+5;
int n,k,a[N],q1[N],h1=1,t1,q2[N],h2=1,t2,ans;
int main(){
k=gi();n=gi();
for (int i=1;i<=n;++i) a[i]=gi();
for (int i=1,j=1;i<=n;++i){
while (h1<=t1&&a[i]>a[q1[t1]]) --t1;
while (h2<=t2&&a[i]<a[q2[t2]]) --t2;
q1[++t1]=q2[++t2]=i;
while (a[q1[h1]]-a[q2[h2]]>k)
if (q1[h1]<q2[h2]) j=q1[h1]+1,++h1;
else j=q2[h2]+1,++h2;
ans=max(ans,i-j+1);
}
printf("%d\n",ans);return 0;
}

POI2010题解的更多相关文章

  1. 洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速$dp\&Floyd$)

    洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速\(dp\&Floyd\)) 标签:题解 阅读体验:https://zybuluo.com/Junl ...

  2. 【字符串】【hash】【倍增】洛谷 P3502 [POI2010]CHO-Hamsters 题解

        这是一道字符串建模+图论的问题. 题目描述 Byteasar breeds hamsters. Each hamster has a unique name, consisting of lo ...

  3. 【题解】[LuoguP3503]「BZOJ2086」[POI2010] Blocks

    题目描述 给出N个正整数a[1..N],再给出一个正整数k,现在可以进行如下操作:每次选择一个大于k的正整数a[i],将a[i]减去1,选择a[i-1]或a[i+1]中的一个加上1.经过一定次数的操作 ...

  4. BZOJ2086: [Poi2010]Blocks

    题解: 想了想发现只需要求出最长的一段平均值>k即可. 平均值的问题给每个数减去k,判断是否连续的一段>0即可. 然后我们发现如果i<j 且 s[i]<s[j],那么 j 对于 ...

  5. BZOJ2083: [Poi2010]Intelligence test

    2083: [Poi2010]Intelligence test Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 241  Solved: 96[Sub ...

  6. BZOJ2091: [Poi2010]The Minima Game

    2091: [Poi2010]The Minima Game Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 243  Solved: 163[Subm ...

  7. BZOJ2079: [Poi2010]Guilds

    2079: [Poi2010]Guilds Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 237  Solved: 181[Submit][Statu ...

  8. BZOJ2084: [Poi2010]Antisymmetry

    2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 187  Solved: 125[Submit] ...

  9. 【BZOJ2084】[Poi2010]Antisymmetry(manarcher)

    [BZOJ2084][Poi2010]Antisymmetry(manarcher) 题面 BZOJ 洛谷 题解 一眼马拉车吧...明显就是在回文串的基础上随便改了改. 似乎还可以魔改回文树,然而我这 ...

随机推荐

  1. Thread的六中状态

    线程共有6种状态:在某一时刻只能是这6种状态之一.这些状态由Thread.State这个枚举类型表示,并且可以通过getState()方法获得当前线程具体的状态类型. NEW:至今尚未启动的线程的状态 ...

  2. rails性能优化

    1,使用Unicorn或者Thin服务器替代默认的webrick.2,静态资源压缩合并,放到云存储上.3,同时可以使用rails的Turbolinks,使用js替换title和body,但也带来了js ...

  3. spring AOP的两种代理

    本篇记录下spring AOP的两种代理,为下一篇AOP实现做下铺垫. 1.JDK动态代理  2.cglib代理 1.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP2.如果目标对象 ...

  4. tomcat jdbc pool

    文中内容主要转自:http://www.open-open.com/lib/view/open1327478028639.html http://www.open-open.com/lib/view/ ...

  5. [one day one question] 有没有免费接收短信验证用于注册的软件或者平台?

    问题描述: 想要批量注册撸羊毛,有手机短信验证码验证,这怎么破? 解决方案: 免费的肯定没有的,不过"一条短信收费一毛钱"倒是有一个,本人是亲自试用过,该平台收不到短信验证码不收费 ...

  6. supervisor初试

    Supervisor (http://supervisord.org) 是一个用 Python 写的进程管理工具,可以很方便的用来启动.重启.关闭进程(不仅仅是 Python 进程).除了对单个进程的 ...

  7. Redis之hash数据结构实现

    参考 https://www.cnblogs.com/ourroad/p/4891648.html https://blog.csdn.net/hjkl950217/article/details/7 ...

  8. [原][译][osgearth]API加载地球(OE官方文档翻译)

    原文参考:http://docs.osgearth.org/en/latest/developer/maps.html#programmatic-map-creation 本人翻译水平有限... 加载 ...

  9. jquery chosen 插件 动态设置+更新选项值

    我要在表单里使用一个select下拉菜单(是不是multiple无所谓),所以选择了jquery chosen这个插件.现在有一个需求,需要根据表单的另一个域来动态加载该select元素的选项. 1 ...

  10. ng-disabled 指令

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script sr ...