NOIP模拟 八十三
csp后第一次模拟,好像以后都和外校联考了。
60+90+25+30
菜。。。。。。。。。。。。。。。。。。
T1T2被大力卡常,T3T4只会暴力。。
冲刺NOIP2021模拟16 树上的数
一眼线段树傻逼题,然后看到5000000,貌似可以带个 log,于是就没多想。
其实扫一遍也挺显然的。。
垃圾oj跑个 n 的5000000跑了一秒六,怕不是上世纪五十年代的剩余产品?
#include<bits/stdc++.h>
#define N 5000050
#define mod 19760817
using namespace std;
int a,b,n,m,dfn[N],siz[N],sum[N<<2],tag[N<<2],head[N],tot,cnt,id[N],ans,tmp,jie;
long long q,f[N];
bool vis[N];
struct jj{int to,nxt;}bian[N];
inline void add(int u,int v)
{ bian[++tot].to=v;
bian[tot].nxt=head[u];
head[u]=tot;
}
inline void work(int x)
{ if(vis[x])return;vis[x]=1;++tmp;
for(int i=head[x];i;i=bian[i].nxt){work(bian[i].to);}
}
signed main()
{ freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%d%d",&n,&m);scanf("%d%d",&a,&b);f[2]=1;
for(int i=3;i<=n;++i)f[i]=((1ll*f[i-1]*a+b)^mod)%(i-1)+1;
for(int i=2;i<=n;++i)add(f[i],i);
long long x,y;
scanf("%lld%lld%lld",&q,&x,&y);
work(q);ans=n-tmp;jie=n-tmp;
for(int i=2;i<=m;++i)
{ q=(((q*x+y)^mod)^(i<<1))%(n-1)+2;
tmp=0;work(q);jie-=tmp;ans^=jie;
}
printf("%d\n",ans);
}
T2冲刺NOIP2021模拟16 时代的眼泪
大概就是个数据结构,然后写了线段树合并,1e6跑两秒跑不出来。。
换用树状数组容斥求子树内的个数就能过了。
#include<bits/stdc++.h>
#define N 1000050
using namespace std;
int w[N],n,head[N],cnt,tot,q,san[N],root[N],id[N],c[N],zhui[N];
long long ans[N];
struct jj{int to,nxt;}bian[N<<1];
inline void add(int u,int v)
{ bian[++tot].to=v;
bian[tot].nxt=head[u];
head[u]=tot;
}
inline int read()
{ int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
inline void write(long long x,char ch='\n')
{ static int sta[35]; int top=0;
if(x<0) putchar('-'),x=-x;
do{sta[++top]=x%10,x/=10;}while(x);
while(top) putchar(sta[top--]+48); putchar(ch);
}
inline void add(int x){for(int i=x;i<=n;i+=i&-i)++c[i];}
inline int query(int x){int res=0;for(int i=x;i>0;i-=i&-i)res+=c[i];return res;}
inline void dfs(int x,int fa)
{ int tmp1=query(id[x]-1),tmp2=query(id[fa]-1);add(id[x]);
for(int i=head[x];i;i=bian[i].nxt)
{ int v=bian[i].to;
if(v==fa)continue;dfs(v,x);
}
if(id[x]!=1)
{ int tmp=query(id[x]-1)-tmp1;
ans[1]+=tmp;if(x!=1)ans[x]-=tmp;
}
if(id[fa]!=1 and x!=1)ans[x]-=(query(id[fa]-1)-tmp2);
}
inline void get_ans(int x,int fa)
{ if(x!=1){ans[x]+=zhui[id[x]-1]+ans[fa];}
for(int i=head[x];i;i=bian[i].nxt)
{ int v=bian[i].to;
if(v==fa)continue;
get_ans(v,x);
}
}
signed main()
{ freopen("tears.in","r",stdin);
freopen("tears.out","w",stdout);
n=read();q=read();
for(int i=1;i<=n;++i)w[i]=read(),san[++cnt]=w[i];
for(int i=1;i<n;++i)
{ int a,b;
a=read();b=read();
add(a,b);add(b,a);
}
sort(san+1,san+1+cnt);cnt=unique(san+1,san+1+cnt)-san-1;
for(int i=1;i<=n;++i)(id[i]=lower_bound(san+1,san+1+cnt,w[i])-san),++zhui[id[i]];
for(int i=1;i<=n;++i)zhui[i]+=zhui[i-1];
tot=0;dfs(1,0);
for(int i=1;i<=q;++i){int x;x=read();write(ans[x]);}
}
T3 冲刺NOIP2021模拟16 传统艺能
线段树维护矩阵。
矩阵状态设计成谁开头,往后再预借一个谁的种类数。
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
#define N 400001
using namespace std;
int n,q;char a[N],c;
struct matrix
{ int c[4][4];
friend matrix operator *(matrix a,matrix b)
{ matrix c;memset(c.c,0,sizeof(c.c));
for(int i=0;i<=3;++i)
for(int j=0;j<=3;++j)
for(int k=0;k<=3;++k)
c.c[i][j]=(c.c[i][j]+a.c[i][k]*b.c[k][j]%mod)%mod;
return c;
}
}tmp,tree[N<<2];
inline void pushup(int x){tree[x]=tree[x<<1]*tree[x<<1|1];}
inline void build(int x,int l,int r)
{ if(l==r)
{ memset(tree[x].c,0,sizeof(tree[x].c));
for(int i=0;i<=3;++i)tree[x].c[i][i]=1;
for(int i=0;i<=3;++i)tree[x].c[a[l]-'A'+1][i]=1;
return;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
pushup(x);
}
inline void ins(int x,int l,int r,int pos,int val)
{ if(l==r)
{ memset(tree[x].c,0,sizeof(tree[x].c));
for(int i=0;i<=3;++i)tree[x].c[i][i]=1;
for(int i=0;i<=3;++i)tree[x].c[val][i]=1;
return;
}
int mid=(l+r)>>1;
if(mid<pos)ins(x<<1|1,mid+1,r,pos,val);
else ins(x<<1,l,mid,pos,val);
pushup(x);
}
inline matrix query(int x,int l,int r,int L,int R)
{ if(l>=L and r<=R)return tree[x];
int mid=(l+r)>>1;
if(mid>=R)return query(x<<1,l,mid,L,R);
else if(mid<L)return query(x<<1|1,mid+1,r,L,R);
else return query(x<<1,l,mid,L,R)*query(x<<1|1,mid+1,r,L,R);
}
signed main()
{ freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
scanf("%lld%lld",&n,&q);scanf("%s",a+1);
build(1,1,n);
for(int i=1;i<=q;++i)
{ int opt,pos,l,r;
scanf("%lld",&opt);
if(opt==1)
{ scanf("%lld %c",&pos,&c);
ins(1,1,n,pos,c-'A'+1);
}
else
{ scanf("%lld%lld",&l,&r);
tmp=query(1,1,n,l,r);
printf("%lld\n",(tmp.c[1][0]+tmp.c[2][0]+tmp.c[3][0])%mod);
}
}
}
T4冲刺NOIP2021模拟16 铺设道路
差分数组,然后削成0,最优就贪心选择。
#include <bits/stdc++.h>
#define N 300050
#define int long long
#define mod 1000000007
using namespace std;
int n, a[N], ans, ans1, ans2, b[N];
queue<int> q;
stack<int> sta;
signed main()
{
freopen("road.in", "r", stdin);
freopen("road.out", "w", stdout);
scanf("%lld", &n);
for (int i = 1; i <= n; ++i)
scanf("%lld", &a[i]);
for (int i = 1; i <= n + 1; ++i)
b[i] = a[i] - a[i - 1];
for (int i = 1; i <= n + 1; ++i)
ans = ans + max(b[i], 0ll);
for (int i = 1; i <= n + 1; ++i)
{
if (b[i] > 0)
q.push(i);
else
{
while (b[i] < 0)
{
int id = q.front();
if (abs(b[id]) <= abs(b[i]))
{
b[i] += b[id];
ans1 = (ans1 + (i - id) * (i - id) % mod * b[id] % mod) % mod;
q.pop();
}
else
{
b[id] += b[i];
ans1 = (ans1 + (i - id) * (i - id) % mod * (-b[i]) % mod) % mod;
b[i] = 0;
}
}
}
}
for (int i = 1; i <= n + 1; ++i)
b[i] = a[i] - a[i - 1];
for (int i = 1; i <= n + 1; ++i)
{
if (b[i] > 0)
sta.push(i);
else
{
while (b[i] < 0)
{
int id = sta.top();
if (abs(b[id]) <= abs(b[i]))
{
b[i] += b[id];
ans2 = (ans2 + (i - id) * (i - id) % mod * b[id] % mod) % mod;
sta.pop();
}
else
{
b[id] += b[i];
ans2 = (ans2 + (i - id) * (i - id) % mod * (-b[i]) % mod) % mod;
b[i] = 0;
}
}
}
}
printf("%lld\n%lld\n%lld\n", ans, ans2, ans1);
}