CSP21
总结:两个题的checker我都自己写了一个,MD,耽误太多时间了,\(Linux\)的\(checker\)使用要加g++ checker.cpp -o 程序名
这题,性质题,首先发现一个树\(n-1\)条边,每次删偶数条边,所以\(n\)必须是奇数,其次我们发现优先删去深度深的点较为优,删完后,我们发现还剩下一些散点散树,再\(dfs\)一遍删掉即可
若先消除根节点,其叶子节点要是无法消除就wa了,所以贪心消除最靠近叶子的节点
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 2e5+5;
int n,p[N],rt,in[N],dep[N],sz[N],id[N];std::vector<int> edge[N];
bool vis[N];
void dfs1(int u)
{
// cout<<in[u]<<" "<<u<<" "<<sz[u]<<endl;
for(auto to:edge[u])
{
if(to==p[u])continue;
dfs1(to);
}
if(in[u]%2==0)//回溯的时候删除,相当于从优先下往上删
{
in[u]=0;
for(auto to:edge[u])in[to]--;
cout<<u<<endl;
vis[u]=1;
}
}
void dfs2(int u)
{
// if(!u)return;
// cout<<u<<endl;
if(in[u]%2==0&&!vis[u])//第二遍可以从上往下删
{
in[u]=0;
vis[u]=1;
cout<<u<<endl;
for(auto to:edge[u])in[to]--;
// return;
}
for(auto to:edge[u])
{
if(to==p[u])continue;
dfs2(to);
}
}
int main()
{
speed();
// freopen("T1.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n;
// cout<<n<<endl;
for(int i=1;i<=n;i++)
{
cin>>p[i];
// cout<<p[i]<<" ";
if(p[i])edge[p[i]].pb(i),in[p[i]]++,in[i]++,edge[i].pb(p[i]);//连双向边删父亲
else rt=i;
}
// cout<<endl;
if(n%2==0)
{
cout<<"NO"<<endl;
return 0;
}
cout<<"YES"<<endl;
// dfs(rt);
// sort(id+1,id+1+n,[&](auto a,auto b){
// return dep[a]>dep[b];
// });
dfs1(rt);
dfs2(rt);
return 0;
}
/*
10
0 1 1 2 2 3 3 4 4 7
*/
建出最短路树,然后优先删深的就行了
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 3e5+5;
struct Id
{
ll to,w,id;
}pre[N];
vector <Id> edge[N];
vector <int> e[N];
ll n,m,k,dis[N],in[N];bool vis[N];
struct node
{
ll u,dis;
bool operator < (const node& A)const
{
return dis>A.dis;
}
};
void dij()
{
for(int i=1;i<=n;i++)dis[i]=1e12;
priority_queue <node> q;
q.push({1,0});dis[1]=0;
while(q.size())
{
int u=q.top().u;q.pop();
if(vis[u])continue;
vis[u]=1;
for(auto [to,w,id]:edge[u])
{
if(dis[to]>dis[u]+w)
{
dis[to]=dis[u]+w;
pre[to].to=u;
pre[to].id=id;
q.push({to,dis[to]});
}
}
}
}
int dep[N],mx;
vector <int> t[N];
void dfs(int u)
{
dep[u]=dep[pre[u].to]+1;
mx=max(mx,dep[u]);
if(u!=1)t[dep[u]].pb(pre[u].id);
for(auto to:e[u])
{
// cout<<u<<"->"<<to<<endl;
dfs(to);
}
}
void put(int u)
{
if(u!=1)cout<<pre[u].id<<" ";
for(auto to:e[u])
{
if(!k)break;
k--;
put(to);
}
}
int main()
{
speed();
// freopen("T2.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>m>>k;ll u,v,w;
for(int i=1;i<=m;i++)
{
cin>>u>>v>>w;
edge[u].pb({v,w,i});edge[v].pb({u,w,i});
}
dij();
for(int i=2;i<=n;i++)e[pre[i].to].pb(i);
if(k>=n-1)
{
cout<<n-1<<endl;
for(int i=2;i<=n;i++)cout<<pre[i].id<<" ";
}else
{
dfs(1);
cout<<k<<endl;
bool f=0;
put(1);
}
return 0;
}
考场暴力,点不水?
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 1e6+6;
inline int read()
{
int x=0,f=1;char ch=getchar_unlocked();
for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void write(ll x)
{
return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
int n,m,Q;
struct OP
{
int op,l,r;ll w;
}op[N];
struct st
{
int l,r;ll w,lz;
}st[N<<2];
inline void pu(int rt)
{
st[rt].w=st[lid].w+st[rid].w;
}
inline void bt(int rt,int l,int r)
{
st[rt].l=l;st[rt].r=r;
st[rt].lz=-1;
if(l==r)
{
st[rt].w=0;return;
}
int mid=l+r>>1;
bt(lid,l,mid);bt(rid,mid+1,r);
pu(rt);
}
inline void pd(int rt)
{
if(st[rt].lz!=-1)
{
int lz=st[rt].lz;st[rt].lz=-1;
st[lid].lz=lz;st[rid].lz=lz;
st[lid].w=lz;st[rid].w=lz;
}
}
inline void update(int rt,int l,int r,int val)
{
if(l<=st[rt].l&&st[rt].r<=r)
{
st[rt].w=val;
st[rt].lz=val;
return;
}
pd(rt);
int mid=(st[rt].l+st[rt].r)>>1;
if(l<=mid)update(lid,l,r,val);
if(r>mid)update(rid,l,r,val);
pu(rt);
return;
}
inline ll query(int rt,int pos)
{
if(st[rt].l==st[rt].r)
{
return st[rt].w;
}
pd(rt);
ll ans=0;
int mid=(st[rt].l+st[rt].r)>>1;
if(pos<=mid)ans+=query(lid,pos);
else if(pos>mid)ans+=query(rid,pos);
// pu(rt);
return ans;
}
struct node
{
int l,r,id;;
bool operator < (const node& A)const
{
return id<A.id;
}
};
int sq,B;
inline void solve()
{
int l,r;
for(int i=1;i<=Q;i++)
{
l=read();r=read();
vector <int> a(n+1,0);
ll ans=0;
for(int j=l;j<=r;j++)
{
if(op[j].op==1)swap(a[op[j].l],a[op[j].r]);
else if(op[j].op==2)
{
for(int k=op[j].l;k<=op[j].r;k++)
{
a[k]=op[j].w;
}
}else
{
ans+=a[op[j].l];
}
}
}
}
inline void solve2()
{
int l,r;
bt(1,1,n);
for(int i=1;i<=Q;i++)
{
l=read();r=read();
update(1,1,n,0);
// bt(1,1,n);
ll ans=0;
for(int j=l;j<=r;j++)
{
if(op[j].op==1)
{
// swap(a[op[j].l],a[op[j].r]);
int t1=query(1,op[j].l),t2=query(1,op[j].r);
update(1,op[j].l,op[j].l,t2);update(1,op[j].r,op[j].r,t1);
}
else if(op[j].op==2)
{
update(1,op[j].l,op[j].r,op[j].w);
}else
{
ans+=query(1,op[j].l);
}
}
// cout<<
ans==0?putchar_unlocked('0'),void(0):write(ans);
putchar_unlocked('\n');
}
}
int main()
{
// freopen("T3.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
n=read();m=read();Q=read();
for(int i=1;i<=m;i++)
{
op[i].op=read();
if(op[i].op==1)
{
op[i].l=read();op[i].r=read();
continue;
}else if(op[i].op==2)
{
op[i].l=read();op[i].r=read();op[i].w=read();
}else op[i].l=read();
}
int l,r;
solve2();
return 0;
}
正解,线段树,但是维护的是时间戳,我们操作\(3\)只和最近一次修改它有关,我们用线段树维护时间戳(即为操作下标),然后问题变为了区间求\([L,R]\)操作\(3\)的和,用树状数组维护时间戳对应的值
卡着线过
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 1e6+5;
inline int read()
{
int x=0,f=1;char ch=getchar_unlocked();
for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void write(ll x)
{
return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
int n,m,Q;
int id[N];
struct BIT
{
ll c[N];
inline int lowbit(int x){return x&-x;}
inline ll query(int x){if(x<1)return 0;ll ans=0;while(x){ans+=c[x];x-=lowbit(x);}return ans;}
inline void add(int x,ll val){if(x<1)return;while(x<=m){c[x]+=val;x+=lowbit(x);}}
}T;
struct Tree
{
int l,r;ll w,lz;
}st[N<<2];
inline void build(int rt,int l,int r)
{
st[rt].l=l;st[rt].r=r;
if(l==r)return;
int mid=l+r>>1;
build(lid,l,mid);build(rid,mid+1,r);
}
inline void pushdown(int rt)
{
if(st[rt].lz)
{
int lz=st[rt].lz;st[rt].lz=0;st[lid].lz=st[lid].w=st[rid].lz=st[rid].w=lz;
}
}
inline void update(int rt,int l,int r,int tim)
{
if(l<=st[rt].l&&st[rt].r<=r)
{
st[rt].w=tim;
st[rt].lz=tim;
return ;
}
int mid=(st[rt].l+st[rt].r)>>1;
pushdown(rt);
if(l<=mid)update(lid,l,r,tim);
if(r>mid)update(rid,l,r,tim);
st[rt].w=max(st[lid].w,st[rid].w);
}
inline int query(int rt,int l,int r)
{
if(st[rt].l==st[rt].r)return st[rt].w;
int mid=st[rt].l+st[rt].r>>1;
pushdown(rt);int ans=0;
if(l<=mid)ans+=query(lid,l,r);
if(r>mid)ans+=query(rid,l,r);
return ans;
}
int l[N],r[N],val[N];ll ans[N];std::vector<pii> pos[N];
int main()
{
// freopen("T3.in","r",stdin);
// freopen("out.out","w",stdout);
n=read();m=read();Q=read();
register int op;build(1,1,n);
for(int i=1;i<=m;i++)
{
op=read();id[i]=op;
if(op==1)
{
l[i]=read();r[i]=read();
int x=query(1,l[i],l[i]),y=query(1,r[i],r[i]);
update(1,l[i],l[i],y);update(1,r[i],r[i],x);
}else if(op==2)
{
l[i]=read();r[i]=read();val[i]=read();
update(1,l[i],r[i],i);
}else
{
l[i]=read();r[i]=query(1,l[i],l[i]);
}
}
register int L,R;
for(int i=1;i<=Q;i++)
{
L=read();R=read();
pos[R].push_back({L,i});
}
for(int i=1;i<=m;i++)
{
if(id[i]==3)T.add(r[i],val[r[i]]);
for(auto [l,j]:pos[i])
{
// cout<<l<<endl;
ans[j]=T.query(i)-T.query(l-1);
}
}
for(int i=1;i<=Q;i++)
{
ans[i]==0?putchar_unlocked('0'),void(0):write(ans[i]);
putchar_unlocked('\n');
}
return 0;
}
有一个关于线段树的优化,因为我们是区间赋值,所以只用一个懒惰标记即可
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 1e6+5;
inline int read()
{
int x=0,f=1;char ch=getchar_unlocked();
for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void write(ll x)
{
return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
int n,m,Q;
int id[N];
struct BIT
{
ll c[N];
inline int lowbit(int x){return x&-x;}
inline ll query(int x){if(x<1)return 0;ll ans=0;while(x){ans+=c[x];x-=lowbit(x);}return ans;}
inline void add(int x,ll val){if(x<1)return;while(x<=m){c[x]+=val;x+=lowbit(x);}}
}T;
struct Tree
{
int l,r;ll lz;
}st[N<<2];
inline void build(int rt,int l,int r)
{
st[rt].l=l;st[rt].r=r;
if(l==r)return;
int mid=l+r>>1;
build(lid,l,mid);build(rid,mid+1,r);
}
inline void pushdown(int rt)
{
if(st[rt].lz)
{
int lz=st[rt].lz;st[rt].lz=0;
st[lid].lz=st[rid].lz=lz;
}
}
inline void update(int rt,int l,int r,int tim)
{
if(l<=st[rt].l&&st[rt].r<=r)
{
st[rt].lz=tim;
return ;
}
int mid=(st[rt].l+st[rt].r)>>1;
pushdown(rt);
if(l<=mid)update(lid,l,r,tim);
if(r>mid)update(rid,l,r,tim);
}
inline int query(int rt,int l,int r)
{
if(st[rt].l==st[rt].r)return st[rt].lz;
if(st[rt].lz)return st[rt].lz;
int mid=st[rt].l+st[rt].r>>1;
pushdown(rt);int ans=0;
if(l<=mid)ans+=query(lid,l,r);
if(r>mid)ans+=query(rid,l,r);
return ans;
}
int l[N],r[N],val[N];ll ans[N];std::vector<pii> pos[N];
int main()
{
// freopen("T3.in","r",stdin);
// freopen("out.out","w",stdout);
n=read();m=read();Q=read();
register int op;build(1,1,n);
for(int i=1;i<=m;i++)
{
op=read();id[i]=op;
if(op==1)
{
l[i]=read();r[i]=read();
int x=query(1,l[i],l[i]),y=query(1,r[i],r[i]);
update(1,l[i],l[i],y);update(1,r[i],r[i],x);
}else if(op==2)
{
l[i]=read();r[i]=read();val[i]=read();
update(1,l[i],r[i],i);
}else
{
l[i]=read();r[i]=query(1,l[i],l[i]);
}
}
register int L,R;
for(int i=1;i<=Q;i++)
{
L=read();R=read();
pos[R].push_back({L,i});
}
for(int i=1;i<=m;i++)
{
if(id[i]==3)T.add(r[i],val[r[i]]);
for(auto [l,j]:pos[i])
{
// cout<<l<<endl;
ans[j]=T.query(i)-T.query(l-1);
}
}
for(int i=1;i<=Q;i++)
{
ans[i]==0?putchar_unlocked('0'),void(0):write(ans[i]);
putchar_unlocked('\n');
}
return 0;
}
逆天,\(hash\)记忆化得了\(80\)分
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 5e6+5;const ull B=233;
string s[N];
int n,m;ull p[600005],len[N];
vector <ull> hs[N];
unordered_map <int,unordered_map<int,int>> f;
inline int read()
{
int x=0,f=1;char ch=getchar_unlocked();
for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void write(int x)
{
return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
inline void calc(int id,int len)
{
// cout<<len<<endl;
hs[id].resize(len+1,0);
for(int i=1;i<=len;i=-~i)
{
hs[id][i]=hs[id][i-1]*B+s[id][i-1]-'a';
if(!p[i])p[i]=p[i-1]*B;
}
}
inline ull get(int id,int l,int r)
{
return hs[id][r]-hs[id][l-1]*p[r-l+1];
}
inline int fen(int x,int y)
{
int r=min(len[x],len[y]);
for(int i=r;i>=1;i--)
{
if(get(y,1,i)==get(x,len[x]-i+1,len[x]))return i;
}
return 0;
}
int main()
{
// freopen("T4.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
n=read();m=read();
p[0]=1;
for(int i=1;i<=n;i=-~i)
{
cin>>s[i];
// __builtin_scanf("%s",s[i]);
// if(i<=2)cout<<s[i]+1<<endl;
len[i]|=s[i].size();
calc(i,len[i]);
}
int l,r;
for(int i=1;i<=m;i=-~i)
{
l=read();r=read();//l houzhui
if(f[l][r])
{
f[l][r]==-1?putchar_unlocked('0'),void(0):write(f[l][r]);
putchar_unlocked('\n');
continue;
}
f[l][r]=fen(l,r);
if(f[l][r]==0)f[l][r]=-1;
f[l][r]==-1?putchar_unlocked('0'),void(0):write(f[l][r]);
putchar_unlocked('\n');
}
return 0;
}