今天血亏。
T1
题目大意:对于给出的一个不保证合法的括号序列,交换括号的位置使得括号序列合法,问最少交换多少个?
题解:送分题。统计未能匹配的括号个数,(x+1)/2即为答案。(然而写的暴力)
T1AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
inline int re_ad()
{
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*10+ch-48,ch=getchar();
return x*f;
}
inline bool read(){char ch=getchar();while(ch!='('&&ch!=')')ch=getchar();return ch=='(';}
int n,lnum=0,rnum=0,l,r,ans=0;
bool fla[100010];
inline void getz()
{
while(l<r)
{
if(fla[l])++lnum;
else{if(!lnum)return;--lnum;}
++l;
}
}
inline void gety()
{
while(l<r)
{
if(!fla[r])++rnum;
else {if(!rnum)return;--rnum;}
--r;
}
}
int main()
{
register int i;
n=re_ad();
for(i=1;i<=n;++i)fla[i]=read(),lnum+=fla[i];
if(lnum*2!=n){cout<<-1<<endl;return 0;}
l=1;r=n;lnum=0;
while(l<r)
{
getz();gety();
if(l>=r)break;
++ans;swap(fla[l],fla[r]);
}
cout<<ans<<endl;
}
T2
题目大意:维护一棵带点权二叉树,支持子树翻转和点权修改,动态询问每个点是否能被平衡树规则访问到。
题解:(数据极水,暴力可过)
一个点能被访问到的充要条件是到根的路径上,所有右父亲都比左儿子大,所有左父亲都比右儿子小
每个点记与父亲节点关系是否合法,每个修改操作影响到的节点都是常数个,树链剖分后维护线段树即可
查询即查询一个点到根路径上是否有非法节点,记得维护是否有相同节点。
T2AC代码(暴力)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
inline int re_ad()
{
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*10+ch-48,ch=getchar();
return x*f;
}
inline int mi(int x,int y){return x<y?x:y;}
inline int ma(int x,int y){return x>y?x:y;}
int n,m,val[100010],ls[100010],rs[100010],fa[100010],nu;
bool ask(int x,int num)
{
if(num==val[x])++nu;if(x==1)return true;
if(x==ls[fa[x]]){if(num>=val[fa[x]])return false;}
else if(num<=val[fa[x]])return false;
return ask(fa[x],num);
}
int main()
{
register int i,op,x,num;
n=re_ad();m=re_ad();
for(i=1;i<=n;++i)
{
val[i]=re_ad();ls[i]=re_ad();rs[i]=re_ad();
if(ls[i])fa[ls[i]]=i;if(rs[i])fa[rs[i]]=i;
}
while(m--)
{
op=re_ad();x=re_ad();
if(op==1){val[x]=re_ad();}
if(op==2){swap(ls[x],rs[x]);}
if(op==3){nu=0;if(ask(x,val[x])&&nu==1)puts("YES");else puts("NO");}
}
}
T3
题目大意:给定一棵n个节点的树,每次询问以x为根的子树中与x的距离不小于k的节点个数。
题解:长链剖分即可。
T3AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
inline int re_ad()
{
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*10+ch-48,ch=getchar();
return x*f;
}
void pu_t(long long x){if(x>9)pu_t(x/10);putchar(x%10+48);}
inline int mi(int x,int y){return x<y?x:y;}
int n,A[2600000],d[2600000],son[2600000],dfn[2600000],tot,Q;
long long f[2600000],ans[2600000];
vector<int> g[2600000];
struct node{int k,id;};
vector<node>ask[2600000];
void dfs(int x)
{
register int i,sz=g[x].size(),v,mx=-1;;
for(i=0;i<sz;++i)
{
v=g[x][i];
dfs(v);
if(d[v]>mx){son[x]=v;mx=d[v];}
}
d[x]=mx+1;
}
void dfs2(int x)
{
register int i,j,sz=g[x].size(),v;
dfn[x]=++tot;
if(son[x])dfs2(son[x]);
for(i=0;i<sz;++i)
{
v=g[x][i];
if(v==son[x])continue;
dfs2(v);
for(j=0;j<=d[v];++j){f[dfn[son[x]]+j]+=f[dfn[v]+j];}
}
f[dfn[x]]=f[dfn[son[x]]]+A[x];
sz=ask[x].size();
long long *fx=f+dfn[x];
for(i=0;i<sz;++i){if(ask[x][i].k<=d[x])ans[ask[x][i].id]=*(fx+ask[x][i].k);}
}
inline void print()
{
register int lim=re_ad();
for (register int i = 1; i <= Q;)
{
register long long res=0;
for (register int j = i; j <= mi(Q, i + lim - 1); j++) res^= ans[j];
i+=lim;
pu_t(res);putchar('\n');
}
}
int main()
{
register int i,an;
n=re_ad();
for(i=1;i<=n;++i)A[i]=re_ad();
for(i=2;i<=n;++i)g[re_ad()].push_back(i);
Q=re_ad();
for(i=1;i<=Q;++i)an=re_ad(),ask[an].push_back((node){re_ad(),i});
dfs(1);dfs2(1);
print();
}