noip模拟27
A.牛半仙的妹子图
比较简单的一道,方法很多,可以使用最小生成树等等..
我们发现每个接受度所到达的目的地是一定的,所以我们预处理出每个接受度所到达的种类集合..
所以我们可以选择权值线段树,先\(Spfa\)求出每个点的路径最小值,然后统计到权值线段树上,累计求前缀和即可..
记得离散化..
A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
#define p() printf("Pass")
#define ll long long int
#define ull unsigned ll
#define re register ll
#define lf double
#define lb lower_bound
#define ub upper_bound
#define mp make_pair
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x);
#define Copy(x,y) memset(y,x,sizeof x);
inline ll read()
{
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
inline void write(ll ss)
{
static int stas[35]; int topps=0;
if(ss<0) putchar('-'),ss=-ss;
do{stas[++topps]=ss%10,ss/=10;}while(ss);
while(topps) putchar(stas[topps--]+48); puts("");
}
} using namespace BSS;
const ll N=7e5+50;
ll m,n,ts,ops,opt,hm,type,maxn,root,tot,sum,mod,alls;
ll head[N],c[N],cnt[N],lsh[N],pre[N],ans[N];
bool vis[N];
struct I { ll u,v,w,nxt; } e[N*2];
struct II { ll ls,rs,sum; } tr[N*64];
struct III { ll path,c; } p[N];
inline bool comp(III i,III j) { return i.path==j.path ? i.c<j.c : i.path<j.path ; }
inline void add(ll u,ll v,ll w)
{
e[++ts].u=u;
e[ts].v=v;
e[ts].w=w;
e[ts].nxt=head[u];
head[u]=ts;
}
queue<ll> que;
void bfs()
{
for(re i=1;i<=n;i++) p[i].path=1e12;
p[hm].path=1; vis[hm]=1;
que.push(hm);
ll u,v,w;
while(que.size())
{
u=que.front(); que.pop();
for(re i=head[u];i;i=e[i].nxt)
{
if(p[e[i].v].path>max(p[u].path,e[i].w))
{
p[e[i].v].path=max(p[u].path,e[i].w);
if(!vis[e[i].v]) que.push(e[i].v);
vis[e[i].v]=1;
}
else continue;
}
vis[u]=0;
}
for(re i=1;i<=n;i++)
{
lsh[++alls]=p[i].path;
}
sort(lsh+1,lsh+1+n);
alls=unique(lsh+1,lsh+1+n)-lsh-1;
for(re i=1;i<=n;i++)
{
p[i].path=lb(lsh+1,lsh+1+alls,p[i].path)-lsh;
}
return ;
}
ll query(ll x,ll l,ll r,ll pos)
{
if(!x) return 0;
if(l==r)
{
return tr[x].sum;
}
ll mid=(l+r)>>1;
if(pos<=mid) return query(tr[x].ls,l,mid,pos);
else return query(tr[x].rs,mid+1,r,pos);
}
void build(ll &x,ll l,ll r)
{
if(!x) x=++tot;
if(l==r)
{
tr[x].sum=cnt[l];
return ;
}
ll mid=(l+r)>>1;
build(tr[x].ls,l,mid); build(tr[x].rs,mid+1,r);
}
inline void Work()
{
sort(p+1,p+1+n,comp);
Fill(vis,0);
for(re i=1;i<=n;i++)
{
if(!vis[p[i].c]) sum++;
vis[p[i].c]=1;
if(p[i].path!=p[i+1].path)
{
cnt[p[i].path]=sum;
}
}
maxn=p[n].path;
for(re i=1;i<=maxn;i++) if(!cnt[i]) cnt[i]=cnt[i-1];
build(root,1,maxn);
ll len,temp,le,ri;
ll temp1,temp2,temp3,temp4,len1,len2;
ll ans1,ans2;
ll lst=0;
for(re i=1;i<=maxn;i++)
{
ans[i]=query(root,1,maxn,i);
}
lsh[maxn+1]=lsh[maxn]+1;
for(re i=1;i<=maxn;i++)
{
len=lsh[i+1]-lsh[i];
pre[i]=pre[i-1]+len*ans[i];
}
for(re i=1;i<=ops;i++)
{
le=read(),ri=read();
if(type)
{
le=le xor lst; le=(le+mod)%mod; le++;
ri=ri xor lst; ri=(ri+mod)%mod; ri++;
if(le>ri) swap(le,ri);
}
temp1=ub(lsh+1,lsh+1+alls,le)-lsh;
len=(le-lsh[temp1-1]);
ans1=ans[temp1-1]*len+pre[temp1-2];
temp2=ub(lsh+1,lsh+1+alls,ri)-lsh;
len=(ri-lsh[temp2-1]+1);
ans2=ans[temp2-1]*len+pre[temp2-2];
lst=ans2-ans1; write(lst);
}
return ;
}
signed main()
{
n=read(); m=read(); ops=read(); hm=read(); type=read();
if(type) mod=read();
for(re i=1;i<=n;i++)
{
p[i].c=read();
}
ll u,v,w;
for(re i=1;i<=m;i++)
{
u=read(),v=read(),w=read();
add(u,v,w); add(v,u,w);
}
bfs(); Work();
return 0;
}
B.牛半仙的妹子Tree
我们发现一个点被标记的条件是:
设当前时间为\(t\),被标记的时间为\(t_0\),感染源为\(u\),当前节点为\(v\),那么需要满足\(t-t_0\geq dep_{lca(u,v)}*2-dep_u-dep-v\)..
于是移项得到:\(t+dep_v \geq dep_{lca(u,v)}*2-dep_u+t_0\)
考虑树剖,在线段树上维护右边的值,并与当前节点进行比较.
这里减去了最右边的\(dep_r\),是因为\(r\)做\(lca\)..
B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
#define p() printf("Pass")
#define ll long long int
#define ull unsigned ll
#define re register ll
#define lf double
#define lb lower_bound
#define ub upper_bound
#define mp make_pair
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x);
#define Copy(x,y) memset(y,x,sizeof x);
inline ll read()
{
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
inline void write(ll ss)
{
static int stas[35]; int topps=0;
if(ss<0) putchar('-'),ss=-ss;
do{stas[++topps]=ss%10,ss/=10;}while(ss);
while(topps) putchar(stas[topps--]+48); puts("");
}
} using namespace BSS;
const ll N=1e5+50;
ll n,m,ts,tot;
ll head[N];
ll dfn[N],rk[N],fa[N],son[N],top[N],dep[N],siz[N];
struct I { ll u,v,nxt; } e[N*2];
struct II { ll l,r,minn,lazy,lazy1; } tr[N*64];
inline void add(ll u,ll v)
{
e[++ts].u=u;
e[ts].v=v;
e[ts].nxt=head[u];
head[u]=ts;
}
void dfs1(ll now,ll dad,ll depth)
{
dep[now]=depth; fa[now]=dad;
siz[now]=1;
for(re i=head[now];i;i=e[i].nxt)
{
if(e[i].v==dad) continue;
dfs1(e[i].v,now,depth+1);
siz[now]+=siz[e[i].v];
if(siz[son[now]]<siz[e[i].v])
{
son[now]=e[i].v;
}
}
return ;
}
void dfs2(ll now,ll high)
{
top[now]=high;
dfn[now]=++tot; rk[tot]=now;
if(!son[now]) return ;
dfs2(son[now],high);
for(re i=head[now];i;i=e[i].nxt)
{
if(e[i].v==fa[now] or e[i].v==son[now]) continue;
dfs2(e[i].v,e[i].v);
}
return ;
}
void spread(ll x)
{
if(tr[x].lazy1)
{
tr[x<<1].minn=tr[x<<1|1].minn=1e11; tr[x<<1].lazy1=tr[x<<1|1].lazy1=1;
tr[x<<1].lazy=0,tr[x<<1|1].lazy=0;
tr[x].lazy1=0;
}
if(tr[x].lazy)
{
ll r1=rk[tr[x<<1].r],r2=rk[tr[x<<1|1].r];
tr[x<<1].minn=min(tr[x<<1].minn,tr[x].lazy-dep[r1]*2);
tr[x<<1|1].minn=min(tr[x<<1|1].minn,tr[x].lazy-dep[r2]*2);
if(!tr[x<<1].lazy) tr[x<<1].lazy=tr[x].lazy;
else tr[x<<1].lazy=min(tr[x<<1].lazy,tr[x].lazy);
if(!tr[x<<1|1].lazy) tr[x<<1|1].lazy=tr[x].lazy;
else tr[x<<1|1].lazy=min(tr[x<<1|1].lazy,tr[x].lazy);
tr[x].lazy=0;
return ;
}
}
void pushup(ll x)
{
tr[x].minn=min(tr[x<<1].minn,tr[x<<1|1].minn);
return ;
}
void update(ll x,ll ql,ll qr,ll val)
{
if(ql>qr) return ;
if(tr[x].l>=ql and tr[x].r<=qr)
{
if(val>=1e9)
{
tr[x].minn=1e11,tr[x].lazy1=1;
tr[x].lazy=0;
return ;
}
tr[x].minn=min(tr[x].minn,val-dep[rk[tr[x].r]]*2);
if(!tr[x].lazy) tr[x].lazy=val;
else tr[x].lazy=min(tr[x].lazy,val);
return ;
}
spread(x);
ll mid=(tr[x].l+tr[x].r)>>1;
if(ql<=mid) update(x<<1,ql,qr,val);
if(qr>=mid+1) update(x<<1|1,ql,qr,val);
pushup(x);
return ;
}
ll query(ll x,ll ql,ll qr)
{
if(tr[x].l>=ql and tr[x].r<=qr)
{
return tr[x].minn;
}
spread(x); ll temp=1e11;
ll mid=(tr[x].l+tr[x].r)>>1;
if(ql<=mid) temp=min(temp,query(x<<1,ql,qr));
if(qr>=mid+1) temp=min(temp,query(x<<1|1,ql,qr));
pushup(x);
return temp;
}
void CHANGE(ll t,ll x)
{
t+=dep[x];
while(top[x]!=1)
{
update(1,dfn[top[x]],dfn[x],t);
x=fa[top[x]];
}
update(1,1,dfn[x],t);
return ;
}
void CLEAR()
{
update(1,1,n,1e11);
return ;
}
void QMIN(ll t,ll x)
{
t-=dep[x];
ll temp=1e11;
while(top[x]!=1)
{
temp=min(temp,query(1,dfn[top[x]],dfn[x]));
if(temp<=t)
{
printf("wrxcsd\n");
return ;
}
x=fa[top[x]];
}
temp=min(temp,query(1,1,dfn[x]));
if(temp<=t)
{
printf("wrxcsd\n");
return ;
}
printf("orzFsYo\n");
return ;
}
void build(ll x,ll l,ll r)
{
tr[x].l=l; tr[x].r=r;
if(tr[x].l==tr[x].r)
{
tr[x].minn=1e11;
return ;
}
ll mid=(l+r)>>1;
build(x<<1,l,mid); build(x<<1|1,mid+1,r);
pushup(x);
return ;
}
signed main()
{
n=read(); m=read();
ll u,v,w;
for(re i=1;i<=n-1;i++)
{
u=read(),v=read();
add(u,v); add(v,u);
}
dfs1(1,0,1); dfs2(1,1);
build(1,1,n);
ll opt;
for(ll i=1;i<=m;i++)
{
opt=read(); u=read();
if(opt==1)
{
CHANGE(i,u);
}
if(opt==2)
{
CLEAR();
}
if(opt==3)
{
QMIN(i,u);
}
}
return 0;
}
C.牛半仙的妹子序列
显然是极长上升子序列,这里安利Yubai的博客,包教包会(不过可能会有套娃,请读者耐心观看)..
C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
#define p() printf("Pass")
#define ll long long int
#define ull unsigned ll
#define re register ll
#define lf double
#define lb lower_bound
#define ub upper_bound
#define mp make_pair
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x);
#define Copy(x,y) memset(y,x,sizeof x);
inline ll read()
{
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
inline void write(ll ss)
{
static int stas[35]; int topps=0;
if(ss<0) putchar('-'),ss=-ss;
do{stas[++topps]=ss%10,ss/=10;}while(ss);
while(topps) putchar(stas[topps--]+48); puts("");
}
} using namespace BSS;
const ll N=2e5+50;
const ll mod=998244353;
ll n;
ll p[N],org[N],f[N];
struct I { ll l,r,lv,maxn,sum; } tr[N*64];
ll nowmax;
ll calc(ll x,ll lmt)
{
if(tr[x].l==tr[x].r) return tr[x].maxn>lmt ? tr[x].sum : 0 ;
if(tr[x<<1|1].maxn>lmt) return (tr[x].lv+calc(x<<1|1,lmt))%mod;
else return calc(x<<1,lmt);
}
void pushup(ll x)
{
tr[x].sum=(tr[x<<1].sum+tr[x<<1|1].sum)%mod;
tr[x].maxn=max(tr[x<<1].maxn,tr[x<<1|1].maxn);
tr[x].lv=calc(x<<1,tr[x<<1|1].maxn);
return ;
}
void update(ll x,ll pos,ll sum,ll maxn)
{
if(tr[x].l==tr[x].r)
{
tr[x].sum+=sum;
tr[x].maxn=maxn;
return ;
}
ll mid=(tr[x].l+tr[x].r)>>1;
if(pos<=mid) update(x<<1,pos,sum,maxn);
else update(x<<1|1,pos,sum,maxn);
pushup(x);
return ;
}
ll query(ll x,ll ql,ll qr)
{
ll temp=0;
if(tr[x].l>=ql and tr[x].r<=qr)
{
temp=calc(x,nowmax);
nowmax=max(nowmax,tr[x].maxn);
return temp;
}
ll mid=(tr[x].l+tr[x].r)>>1;
if(qr>=mid+1) temp=(temp+query(x<<1|1,ql,qr))%mod;
if(ql<=mid) temp=(temp+query(x<<1,ql,qr))%mod;
return temp;
}
void build(ll x,ll l,ll r)
{
tr[x].l=l; tr[x].r=r;
if(tr[x].l==tr[x].r) return ;
ll mid=(tr[x].l+tr[x].r)>>1;
build(x<<1,l,mid); build(x<<1|1,mid+1,r);
return ;
}
signed main()
{
n=read();
for(re i=1;i<=n;i++)
{
p[i]=read();
org[p[i]]=i;
}
build(1,1,n);
for(re i=1;i<=n;i++)
{
nowmax=0;
f[i]=query(1,1,p[i]-1);
if(!f[i]) f[i]=1;
update(1,p[i],f[i],i);
}
ll temp=0,ans=0;
for(re i=n;i>=1;i--)
{
if(org[i]>temp)
{
temp=max(temp,org[i]);
ans=(ans+f[org[i]])%mod;
}
}
write(ans%mod);
return 0;
}

浙公网安备 33010602011771号