@SovietPower
2024-03-31T00:12:32.000000Z
字数 13290
阅读 318
其它
beats
/*
94908kb 47472ms
支持下面几种操作:
1.给一个区间[L,R] 加上一个数x
2.把一个区间[L,R] 里小于x 的数变成x
3.把一个区间[L,R] 里大于x 的数变成x
4.求区间[L,R] 的和
5.求区间[L,R] 的最大值
6.求区间[L,R] 的最小值
$Solution$
区间取max、min并维护区间和是普通线段树无法处理的。
对于操作二,维护区间最小值mn、最小值个数t、严格次小值se。
当mn>=x时,不需要改变,return;se>x>mn时,sum=sum+(x-mn)*t,打上区间max标记;
当x>=se>mn时,不会做,继续递归分别处理两个子区间,直到遇到前两种情况。
操作三同理,维护最大值、最大值个数、次大值。
复杂度$O(m\log^2n)$,常表现为$O(mlogn)$。
有两个修改(max,min),太恶心了。。
比如:取min的时候不仅是改最大值,最小值也可能改(当然了。。然而这题就是忘了)。
最大值改了min标记也一定改(最大值是算了当前min标记后的)。
还有max标记也可能改,注意是取min而不是直接赋值(还有加法影响这个标记,原先的最大值并不一定是由这个标记得到的)。
还有min,max可能会使得区间变为同一个数(第一句话的情况),这就需要特判然后把sum,次小值,次大值初始化掉。
还有如果mn没有跟mx一起变为v(上一种情况),但是可能mn<v<=se,还要让次小值取个min。
还有常数太大。。考虑把min,max标记去掉,直接在父节点更新,并在适合的时候下传。-> 47s->40s.
*/
struct Segment_Tree
{
#define S N<<2
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int mn[S],smn[S],tmn[S],mx[S],smx[S],tmx[S],sz[S],add[S],tagmn[S],tagmx[S];
LL sum[S];
#undef S
inline void Update(int rt)
{
int l=ls,r=rs; sum[rt]=sum[l]+sum[r];
if(mn[l]<mn[r]) mn[rt]=mn[l],smn[rt]=std::min(smn[l],mn[r]),tmn[rt]=tmn[l];
else if(mn[l]>mn[r]) mn[rt]=mn[r],smn[rt]=std::min(smn[r],mn[l]),tmn[rt]=tmn[r];
else mn[rt]=mn[l],smn[rt]=std::min(smn[l],smn[r]),tmn[rt]=tmn[l]+tmn[r];
if(mx[l]>mx[r]) mx[rt]=mx[l],smx[rt]=std::max(smx[l],mx[r]),tmx[rt]=tmx[l];
else if(mx[l]<mx[r]) mx[rt]=mx[r],smx[rt]=std::max(smx[r],mx[l]),tmx[rt]=tmx[r];
else mx[rt]=mx[l],smx[rt]=std::max(smx[l],smx[r]),tmx[rt]=tmx[l]+tmx[r];
}
inline void Add(int x,int v)
{
add[x]+=v, mn[x]+=v, mx[x]+=v, sum[x]+=1ll*v*sz[x];
if(smn[x]!=INF) smn[x]+=v;
if(smx[x]!=-INF) smx[x]+=v;
if(tagmn[x]!=INF) tagmn[x]+=v;
if(tagmx[x]!=-INF) tagmx[x]+=v;
}
inline void Min(int x,int v)
{
if(v<mx[x])
{
sum[x]-=1ll*tmx[x]*(mx[x]-v);
mx[x]=v, mn[x]=std::min(mn[x],v);//!
tagmn[x]=v/*! 首先要比最大值小才可能(且一定会)更新min标记*/,
tagmx[x]=std::min(tagmx[x],v);//!
if(mn[x]==mx[x]) sum[x]=1ll*sz[x]*v, tmn[x]=tmx[x]=sz[x], smn[x]=INF, smx[x]=-INF;//!
else smn[x]=std::min(smn[x],v);//!
}
}
inline void Max(int x,int v)
{
if(v>mn[x])
{
sum[x]+=1ll*tmn[x]*(v-mn[x]);
mn[x]=v, mx[x]=std::max(mx[x],v);
tagmx[x]=v, tagmn[x]=std::max(tagmn[x],v);
if(mn[x]==mx[x]) sum[x]=1ll*sz[x]*v, tmn[x]=tmx[x]=sz[x], smn[x]=INF, smx[x]=-INF;
else smx[x]=std::max(smx[x],v);
}
}
void PushDown(int rt)
{
if(add[rt]) Add(ls,add[rt]), Add(rs,add[rt]), add[rt]=0;
if(tagmn[rt]!=INF) Min(ls,tagmn[rt]), Min(rs,tagmn[rt]), tagmn[rt]=INF;
if(tagmx[rt]!=-INF) Max(ls,tagmx[rt]), Max(rs,tagmx[rt]), tagmx[rt]=-INF;
}
void Build(int l,int r,int rt)
{
sz[rt]=r-l+1, tagmn[rt]=INF, tagmx[rt]=-INF;
if(l==r)
{
tmn[rt]=tmx[rt]=1;
sum[rt]=mn[rt]=mx[rt]=read(), smn[rt]=INF, smx[rt]=-INF;
return;
}
Build(l,l+r>>1,ls), Build((l+r>>1)+1,r,rs);
Update(rt);
}
void Modify_Add(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R) {Add(rt,v); return;}
PushDown(rt);
int m=l+r>>1;
if(L<=m) Modify_Add(lson,L,R,v);
if(m<R) Modify_Add(rson,L,R,v);
Update(rt);
}
void Modify_Max(int l,int r,int rt,int L,int R,int v)
{
if(mn[rt]>=v) return;
if(L<=l && r<=R && smn[rt]>v) {Max(rt,v); return;}
PushDown(rt);
int m=l+r>>1;
if(L<=m) Modify_Max(lson,L,R,v);
if(m<R) Modify_Max(rson,L,R,v);
Update(rt);
}
void Modify_Min(int l,int r,int rt,int L,int R,int v)
{
if(mx[rt]<=v) return;
if(L<=l && r<=R && smx[rt]<v) {Min(rt,v); return;}
PushDown(rt);
int m=l+r>>1;
if(L<=m) Modify_Min(lson,L,R,v);
if(m<R) Modify_Min(rson,L,R,v);
Update(rt);
}
int Query_Max(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return mx[rt];
PushDown(rt);
int m=l+r>>1;
if(L<=m)
if(m<R) return std::max(Query_Max(lson,L,R),Query_Max(rson,L,R));
else return Query_Max(lson,L,R);
else return Query_Max(rson,L,R);
}
int Query_Min(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return mn[rt];
PushDown(rt);
int m=l+r>>1;
if(L<=m)
if(m<R) return std::min(Query_Min(lson,L,R),Query_Min(rson,L,R));
else return Query_Min(lson,L,R);
else return Query_Min(rson,L,R);
}
LL Query_Sum(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return sum[rt];
PushDown(rt);
int m=l+r>>1;
if(L<=m)
if(m<R) return Query_Sum(lson,L,R)+Query_Sum(rson,L,R);
else return Query_Sum(lson,L,R);
else return Query_Sum(rson,L,R);
}
}T;
int main()
{
#define S 1,n,1
int n=read(); T.Build(S);
for(int m=read(),opt,l,r; m--; )
{
opt=read(),l=read(),r=read();
if(opt==1) T.Modify_Add(S,l,r,read());
else if(opt==2) T.Modify_Max(S,l,r,read());
else if(opt==3) T.Modify_Min(S,l,r,read());
else if(opt==4) printf("%lld\n",T.Query_Sum(S,l,r));
else if(opt==5) printf("%d\n",T.Query_Max(S,l,r));
else printf("%d\n",T.Query_Min(S,l,r));
}
#undef S
return 0;
}
mex
/*
每次询问一个区间内最小没有出现过的自然数。
考虑[1,i]的mex[i],显然是单调的
而对于[l,r]与[l+1,r],如果nxt[a[l]]>r,那么[l+1,r]中所有>a[l]的数显然要改成a[l]
询问排序,离散化,预处理下nxt[],剩下就是线段树的区间更新、查询了
离散化的时候>=n的全部看做n就好了
查询时是只需查r点的(l之前能更新r的已经更新完了,初始时是[1,r],r点现在就是[l,r]了)
单点即可不需要PushUp(也不好得某个区间的mex)
非叶节点上的mex完全可以代替tag
离散化需要注意
*/
#define now node[rt]
#define lson node[node[rt].ls]
#define rson node[node[rt].rs]
const int N=2e5+5,INF=1e7;
int n,m,A[N],mex[N]/*不要和A混用*/,tmp[N],nxt[N],las[N],ans[N];
bool vis[N];
struct Ques
{
int l,r,id;
Ques() {}
Ques(int l,int r,int id): l(l),r(r),id(id) {}
bool operator <(const Ques &x)const {return l<x.l;}
}q[N];
struct Seg_Tree
{
int tot;
struct Node
{
int ls,rs,mex;
}node[N<<1];
inline void Upd(int &x,int v) {x=std::min(x,v);}
inline void PushDown(int rt)
{
Upd(lson.mex,now.mex), Upd(rson.mex,now.mex);
now.mex=INF;
}
void Build(int l,int r)
{
int rt=tot++;
if(l==r) now.mex = mex[l];
else
{
int m=l+r>>1; now.mex=INF;
now.ls=tot, Build(l,m);
now.rs=tot, Build(m+1,r);
}
}
void Update(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R) Upd(now.mex,v);
else
{
if(now.mex<INF) PushDown(rt);
int m=l+r>>1;
if(L<=m) Update(l,m,now.ls,L,R,v);
if(m<R) Update(m+1,r,now.rs,L,R,v);
}
}
int Query(int l,int r,int rt,int p)
{
if(l==r) return now.mex;
if(now.mex<INF) PushDown(rt);
int m=l+r>>1;
if(p<=m) return Query(l,m,now.ls,p);
else return Query(m+1,r,now.rs,p);
}
}t;
#undef now
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
int Find(int x,int r)
{
int l=1,m;
while(l<r)
{
if(tmp[(m=l+r>>1)]<x) l=m+1;
else r=m;
}
return l;
}
int main()
{
n=read(),m=read();
for(int i=1; i<=n; ++i) tmp[i]=A[i]=std::min(n,read());
std::sort(tmp+1,tmp+1+n);
int cnt=1;
for(int i=2; i<=n && !(tmp[i]==n&&tmp[i+1]==n); ++i)
if(tmp[i]!=tmp[i-1]) tmp[++cnt]=tmp[i];
for(int k=0,p,i=1; i<=n; ++i)
{
vis[p=Find(A[i],cnt)]=1;
if(A[i]==k)//只有在当前最小值出现时才更新。。mex...
while(vis[p])//p-1,vis[k]?
{
++k;
if(tmp[++p]!=k) break;//离散化后
}
mex[i]=k;
}
t.Build(1,n);
for(int i=0; i<=n; ++i) las[i]=n+1;
for(int tp,i=n; i; --i) nxt[i]=las[tp=Find(A[i],cnt)], las[tp]=i;//!
for(int l,i=1; i<=m; ++i) l=read(), q[i]=Ques(l,read(),i);
std::sort(q+1,q+1+m);
for(int now=1,i=1; i<=m; ++i)
{
while(now<q[i].l)
t.Update(1,n,0,now+1,nxt[now]-1,A[now]), ++now;
ans[q[i].id]=t.Query(1,n,0,q[i].r);
}
for(int i=1; i<=m; ++i) printf("%d\n",ans[i]);
return 0;
}
区间加、乘
int n,mod,Sum[N<<2],aTag[N<<2],mTag[N<<2];
inline void PushUp(int rt)
{
Sum[rt]=(Sum[rt<<1]+Sum[rt<<1|1])%mod;
}
inline void PushDown(int m,int rt)
{
if(mTag[rt]!=1)
{
mTag[rt<<1]=1ll*mTag[rt<<1]*mTag[rt]%mod;
mTag[rt<<1|1]=1ll*mTag[rt<<1|1]*mTag[rt]%mod;
aTag[rt<<1]=1ll*aTag[rt<<1]*mTag[rt]%mod;
aTag[rt<<1|1]=1ll*aTag[rt<<1|1]*mTag[rt]%mod;
Sum[rt<<1]=1ll*Sum[rt<<1]*mTag[rt]%mod;
Sum[rt<<1|1]=1ll*Sum[rt<<1|1]*mTag[rt]%mod;
mTag[rt]=1;
}
if(aTag[rt])
{
aTag[rt<<1]+=aTag[rt], aTag[rt<<1]%=mod;
aTag[rt<<1|1]+=aTag[rt], aTag[rt<<1|1]%=mod;
Sum[rt<<1]=(1ll*Sum[rt<<1]+1ll*(m-(m>>1))*aTag[rt]%mod)%mod;
Sum[rt<<1|1]=(1ll*Sum[rt<<1|1]+1ll*(m>>1)*aTag[rt]%mod)%mod;
aTag[rt]=0;
}
}
void Build(int l,int r,int rt)
{
mTag[rt]=1;
if(l==r)
{
Sum[rt]=read()%mod;
return;
}
int m=l+r>>1;
Build(l,m,rt<<1),Build(m+1,r,rt<<1|1);
PushUp(rt);
}
void Modify_Add(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R)
{
aTag[rt]+=v;
if(aTag[rt]>=mod) aTag[rt]-=mod;
Sum[rt]=(1ll*Sum[rt]+1ll*v*(r-l+1))%mod;
return;
}
PushDown(r-l+1,rt);
int m=l+r>>1;
if(L<=m) Modify_Add(l,m,rt<<1,L,R,v);
if(m<R) Modify_Add(m+1,r,rt<<1|1,L,R,v);
PushUp(rt);
}
void Modify_Mult(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R)
{
aTag[rt]=1ll*aTag[rt]*v%mod;
mTag[rt]=1ll*mTag[rt]*v%mod;
Sum[rt]=1ll*Sum[rt]*v%mod;
return;
}
PushDown(r-l+1,rt);
int m=l+r>>1;
if(L<=m) Modify_Mult(l,m,rt<<1,L,R,v);
if(m<R) Modify_Mult(m+1,r,rt<<1|1,L,R,v);
PushUp(rt);
}
int Query_Sum(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return Sum[rt];
PushDown(r-l+1,rt);
int m=l+r>>1;long long res=0;
if(L<=m) res+=Query_Sum(l,m,rt<<1,L,R), res%=mod;
if(m<R) res+=Query_Sum(m+1,r,rt<<1|1,L,R), res%=mod;
return res;
}
#define MOD(x) x>=mod&&(x-=mod)
#define ADD(x,v) (x+=v)>=mod&&(x-=mod)
#define gc() getchar()
#define MAXIN 200000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5;
int n,mod,val[N],Enum,H[N],nxt[N<<1],to[N<<1],sz[N],son[N],top[N],fa[N],dep[N],dfn[N],ref[N];
//char IN[MAXIN],*SS=IN,*TT=IN;
struct Segment_Tree
{
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
#define S N<<2
int t[S],tag[S];
#undef S
#define Add(rt,v,l) t[rt]+=1ll*(l)*v%mod, MOD(t[rt]), ADD(tag[rt],v)
#define Update(rt) t[rt]=t[ls]+t[rs], MOD(t[rt])
inline void PushDown(int rt,int m)
{
Add(ls,tag[rt],m-(m>>1)), Add(rs,tag[rt],(m>>1)), tag[rt]=0;
}
void Build(int l,int r,int rt)
{
if(l==r) {t[rt]=val[ref[l]]; return;}
int m=l+r>>1; Build(lson), Build(rson), Update(rt);
}
void Modify(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R) {Add(rt,v,r-l+1); return;}
if(tag[rt]) PushDown(rt,r-l+1);
int m=l+r>>1;
if(L<=m) Modify(lson,L,R,v);
if(m<R) Modify(rson,L,R,v);
Update(rt);
}
int Query(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return t[rt];
if(tag[rt]) PushDown(rt,r-l+1);
int m=l+r>>1,res=0;
if(L<=m) res+=Query(lson,L,R);
if(m<R) res+=Query(rson,L,R);
return res>=mod?res-mod:res;
}
}T;
#define S 1,n,1
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline void AE(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void DFS1(int x)
{
int mx=0; sz[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=fa[x])
fa[v]=x, dep[v]=dep[x]+1, DFS1(v), sz[v]>mx&&(mx=sz[v],son[x]=v), sz[x]+=sz[v];
}
void DFS2(int x,int tp)
{
static int Index=0;
top[x]=tp, ref[dfn[x]=++Index]=x;
if(son[x])
{
DFS2(son[x],tp);
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=fa[x] && v!=son[x]) DFS2(v,v);
}
}
int Query_LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
x=fa[top[x]];
}
return dep[x]>dep[y]?y:x;
}
void ChainAdd(int w,int u,int v)
{
while(top[u]!=top[v])
{
dep[top[u]]<dep[top[v]]&&(std::swap(u,v),0);
T.Modify(S,dfn[top[u]],dfn[u],w), u=fa[top[u]];
}
dep[u]>dep[v]&&(std::swap(u,v),0), T.Modify(S,dfn[u],dfn[v],w);
}
int Query(int u,int v)
{
LL res=0;
while(top[u]!=top[v])
{
dep[top[u]]<dep[top[v]]&&(std::swap(u,v),0);
res+=T.Query(S,dfn[top[u]],dfn[u]), u=fa[top[u]];
}
dep[u]>dep[v]&&(std::swap(u,v),0);
return (res+T.Query(S,dfn[u],dfn[v]))%mod;
}
int main()
{
int n=read(),m=read(),root=read(); ::n=n, mod=read();
for(int i=1; i<=n; ++i) val[i]=read();
for(int i=1; i<n; ++i) AE(read(),read());
DFS1(root), DFS2(root,root), T.Build(S);
for(int x; m--; )
{
switch(read())
{
case 1: ChainAdd(read(),read(),read()); break;
case 2: printf("%d\n",Query(read(),read())); break;
case 3: x=read(), T.Modify(S,dfn[x],dfn[x]+sz[x]-1,read()); break;
case 4: x=read(), printf("%d\n",T.Query(S,dfn[x],dfn[x]+sz[x]-1)); break;
}
}
return 0;
}
struct BIT
{
int n,t[N*4];//2n!
#define lb(x) (x&-x)
inline void Add(int p)
{
for(; p<=n; p+=lb(p)) ++t[p];
}
inline void Delete(int p)
{
for(; p<=n; p+=lb(p)) --t[p];
}
inline int Query(int p)
{
int res=0;
for(; p; p^=lb(p)) res+=t[p];
return res;
}
void Init(int nn) {
//...
}
inline int Kth(int k)
{
int l=1,r=n,mid;
while(l<r)
if(Query(mid=l+r>>1)<k) l=mid+1;
else r=mid;
return l;
}
}T;
并查集
int Getfa(int x) {
return x==fa[x]?x:fa[x]=Getfa(fa[x]);
}
if((r1=Getfa(x))!=(r2=Getfa(y)))
{
fa[r2]=r1; tag[r1]|=tag[r2];
if(mx[r2]>mx[r1]) smx[r1]=std::max(mx[r1],smx[r2]), mx[r1]=mx[r2];
else smx[r1]=std::max(smx[r1],mx[r2]);
}
KMP
int fail[N];
char s[N],p[N];
void Get_Fail()
{
fail[0]=fail[1]=0;
int l=strlen(s+1);
for(int j=0,i=2; i<=l; ++i)
{
while(j && s[i]!=s[j+1]) j=fail[j];
fail[i]= s[i]==s[j+1]?++j:0;
}
}
void KMP()
{
int l=strlen(p+1),ls=strlen(s+1);
for(int i=1,j=0; i<=l; ++i)
{
while(j && p[i]!=s[j+1]) j=fail[j];
if(p[i]==s[j+1]) ++j;
if(j==ls) printf("%d\n",i-ls+1);
}
for(int i=1; i<=ls; ++i)
printf("%d ",fail[i]);
}
scanf("%s%s",p+1,s+1);
Get_Fail();
KMP();
Dijkstra
inline void AE(int u,int v,int w)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w;
}
void Dijkstra(int s,int t,int n)
{
static int dis[N];
static bool vis[N];
static std::priority_queue<pr> q;
memset(dis,0x3f,sizeof dis);
dis[s]=dis[s+n]=0, q.push(mp(0,s));
while(!q.empty())
{
int x=q.top().second; q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if(dis[v=to[i]]>dis[x]+len[i])
q.push(mp(-(dis[v]=dis[x]+len[i]),v));
}
printf("%d\n",dis[t]);
}
差分约束
考虑最短路中的松弛操作:if(dis[v]>dis[x]+w) dis[v]=dis[x]+w
,也就是强制使得满足。
所以对于的限制,可以连一条边。这样求的最大值,就是求的最短路。
如果限制是,同理连边。的最小值就是求的最长路。
如果两种限制都有,就把变成。
解的存在性:
比如求的最大值:若图中存在负环,则的最短路无穷小,则不存在最大值(无解)。
若和就不在同一连通块,则的最短路无穷大,最大值无穷大(或者存在无数多解)。
否则有解。
可以根据入队次数判负环,也可以据此判正环。虽然效率都不高就是了。不能求最长路(本质是贪心)。
如何判断解唯一:
对原图求一遍最短路。将原图取反,边权取反,求一遍最长路。
一个标号对应的是能取到的最小值,一个是最大值。如果相同则解唯一。
/*
差分约束:对于 n[a] - n[b] <= w 的不等式,可以转化成 n[a] <= n[b] + w
换个形式 dis[a] <= dis[b] + w(a,b)
用SPFA做,dis[a]>dis[b]+w(a,b) 时会进行松弛
求最小值用最长路,求最大值用最短路
1.>= 求最小值。为什么是最长路?如果是最短路,很多条件可能不被满足,
(SPFA松弛时是将 dis[a]>dis[b]+w(a,b) -> dis[a]=dis[b]+w(a,b))
2.<= 求最大值。为什么是最短路?因为要满足所有小于等于的条件,只有最短的路才能满足图中所有约束条件;如果比最短路长,可能有些条件不被满足
3.如果出现没有等号的项,用整数的连续性
*/
bool SPFA()
{
for(int i=1; i<=T; ++i) dis[i]=-INF,tm[i]=0;
tm[0]=dis[0]=0, q.push(0);
while(!q.empty())
{
int x=q.front();q.pop();
inq[x]=0;
for(int i=H[x]; i; i=nxt[i])
if(dis[to[i]]<dis[x]+val[i])
{
dis[to[i]]=dis[x]+val[i];
if(!inq[to[i]])
{
if(++tm[to[i]]>T) return 0;
inq[to[i]]=1,q.push(to[i]);
}
}
}
return 1;
}
bool Check(int x)
{
Enum=0, memset(H,0,sizeof H);
for(int i=1; i<8; ++i) AddEdge(16+i,i,R[i]-x);
for(int i=8; i<=T; ++i) AddEdge(i-8,i,R[i]);
for(int i=1; i<=T; ++i) AddEdge(i,i-1,-B[i]),AddEdge(i-1,i,0);
AddEdge(0,T,x), AddEdge(T,0,-x);
return SPFA();
}