CSP 后多校八
A. 回文
签到题.
A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
#define int long long
#define lf long double
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define lbt(x) ((x)&(-(x)))
#define Fill(x,y) memset(x,y,sizeof(x))
#define Copy(x,y) memcpy(x,y,sizeof(x))
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
return cit?(-w):w;
};
} using namespace BSS;
const int mod=993244853,N=505;
char ch[N][N];
int m,n,sum,len,ans;
int dp[2][N][N];
// (x,n+m-x+1-i)
auto inc=[](int &x,int y)->void{ x+=y,x-=(x>=mod)*mod; };
signed main(){
File(palin);
n=read(),m=read(),sum=n+m-1,len=(sum>>1)+(sum&1);
for(int i=1;i<=n;i++) scanf("%s",ch[i]+1);
if(ch[1][1]!=ch[n][m]) puts("0"),exit(0);
dp[1][1][n]=1;
for(int l=1;l<len;l++){
int now=(l&1),nxt=now^1;
for(int i=1,lmi=min(n,l);i<=lmi;i++){
int j=l-i+1;
for(int x=n,lmx=n+1-l;x>=lmx;x--){
int y=n+m-x+1-l;
if(ch[i+1][j]==ch[x-1][y]){
inc(dp[nxt][i+1][x-1],dp[now][i][x]);
}
if(ch[i+1][j]==ch[x][y-1]){
inc(dp[nxt][i+1][x],dp[now][i][x]);
}
if(ch[i][j+1]==ch[x-1][y]){
inc(dp[nxt][i][x-1],dp[now][i][x]);
}
if(ch[i][j+1]==ch[x][y-1]){
inc(dp[nxt][i][x],dp[now][i][x]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) dp[now][i][j]=0;
}
}
if(sum&1){
for(int i=1;i<=n;i++) inc(ans,dp[len&1][i][i]);
}
else{
int now=len&1;
for(int i=1;i<=n;i++){
for(int x=i-1;x<=i+1;x++){
int j=len-i+1,y=n+m-x+1-len;
// if(dp[now][i][x] and abs(i-x)+abs(y-j)==1) cout<<i<<' '<<j<<' '<<x<<' '<<y<<endl;
if(abs(i-x)+abs(y-j)==1) inc(ans,dp[now][i][x]);
}
}
}
printf("%lld\n",ans),exit(0);
}
B. 快速排序
大模拟,观察题目手玩一下样例好像就行.
B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
// #define int long long
#define lf long double
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define lbt(x) ((x)&(-(x)))
#define Fill(x,y) memset(x,y,sizeof(x))
#define Copy(x,y) memcpy(x,y,sizeof(x))
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
return cit?(-w):w;
};
} using namespace BSS;
const int N=5e5+21;
char ch[N];
int m,n,cnt;
int val[N],tmp[N];
auto Work=[]()->void{
n=read(),cnt=0; int flag=1;
for(int i=0;i<=n+5;i++) val[i]=0;
for(int i=1;i<=n;i++){
scanf("%s",ch+1);
if(ch[1]=='n'){ val[i]=-1,flag=0; continue; }
for(int j=1,lmj=strlen(ch+1);j<=lmj;j++){
val[i]=(val[i]<<3)+(val[i]<<1)+(ch[j]^48);
}
tmp[++cnt]=val[i];
}
sort(tmp+1,tmp+1+cnt); int lst=1,now=-1;
for(int i=1;i<=n;i++){
if(!(~val[i])) { printf("nan "); continue; }
if(val[i]<now) continue;
int nxt=lb(tmp+1,tmp+1+cnt,val[i])-tmp;
for(int j=lst;j<=nxt;j++) printf("%d ",tmp[j]),now=tmp[j],tmp[j]=-1;
lst=nxt+1;
}
puts("");
};
signed main(){
File(qsort);
for(int Ts=read();Ts;Ts--) Work();
}
C. 混乱邪恶
挺牛逼的一道题,没有被启发向正解的方向,但是有被启发到.
题目中给出几个信息:互不相同的几个数,范围在 \(1e6\) 以内,个数是 \(\dfrac{2m}{3}\) 以上.
可以发现,如果没啥经验的话,基本无从下手,这个时候能做的就只有大力猜测..
到了猜测结论这一步的时候就应该一次次地考虑很多方向地去猜、证明,不会证就应该大力手玩,或者直接码然后通过断言、大样例等自行验证.
首先会很自然地考虑到排序,然后考虑分组.
之后一个可能猜到的方向就是挪动组之间的数,然后消去差值.
证明的话,发现有至少 \(\frac{1}{3}\) 个数是相邻的( 即差值为 \(1\) ),于是就可以消去那些不是相邻的了.
C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
#define int long long
#define lf long double
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define lbt(x) ((x)&(-(x)))
#define Fill(x,y) memset(x,y,sizeof(x))
#define Copy(x,y) memcpy(x,y,sizeof(x))
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
return cit?(-w):w;
};
} using namespace BSS;
const int N=1e6+21;
int m,n,sum,cnt;
int a[N],o[N],ans[N];
struct I { int u,v,w; } p[N];
signed main(){
File(chaoticevil);
puts("NP-Hard solved");
n=read(),m=read(),m=n;
for(int i=1;i<=n;i++) a[i]=o[i]=read();
if(m&1) a[++m]=0; sort(a+1,a+1+m);
for(int i=2;i<=m;i+=2){
p[++cnt].u=a[i],p[cnt].v=a[i-1],p[cnt].w=a[i]-a[i-1],sum+=p[cnt].w,ans[a[i]]=1;
}
sort(p+1,p+1+cnt,[](I i,I j){ return i.w>j.w; });
for(int i=1;i<=cnt;i++){
if(p[i].w*2>sum) continue;
sum-=p[i].w*2,ans[p[i].u]^=1,ans[p[i].v]^=1;
}
assert(!sum);
for(int i=1;i<=n;i++){
printf("%d ",ans[o[i]] ? 1 : -1 );
}
exit(0);
}
D. 校门外歪脖树上的鸽子
牛逼数据结构.
一个牛逼的想法,就是自己的贡献可以存到兄弟节点上.
对于一些边界问题,比如自己没有兄弟给自己加贡献,那就凭空创造一个兄弟.
感觉数据结构对于问题的转化总是很 \(native\).
D_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
#define int long long
#define lf long double
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define lbt(x) ((x)&(-(x)))
#define Fill(x,y) memset(x,y,sizeof(x))
#define Copy(x,y) memcpy(x,y,sizeof(x))
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
return cit?(-w):w;
};
} using namespace BSS;
const int N=2e6+21;
int m,n,rt,ops,cnt,bit;
int fa[N],le[N],ri[N],rk[N],tp[N],id[N];
int dfn[N],top[N],siz[N],dep[N];
int hson[N],lson[N],rson[N];
struct Seg_Tree{
#define ls (x<<1)
#define rs (x<<1|1)
struct O { int w,sum,lzy; } tr[N<<2];
inline void getval(int x,int w){ tr[x].lzy+=w,tr[x].w+=w*tr[x].sum; }
inline void pushup(int x){ tr[x].w=tr[ls].w+tr[rs].w; }
inline void spread(int x){
int &lzy=tr[x].lzy; if(!lzy) return ;
getval(ls,lzy),getval(rs,lzy),lzy=0;
}
inline void opd(int x,int l,int r,int px,int w){
if(l==r) return tr[x].sum+=w,void();
int mid=(l+r)>>1;
px<=mid ? opd(ls,l,mid,px,w) : opd(rs,mid+1,r,px,w) ;
tr[x].sum=tr[ls].sum+tr[rs].sum;
}
inline void upd(int x,int l,int r,int ql,int qr,int w){
if(ql>qr) return ;
if(l>=ql and r<=qr) return getval(x,w),void();
int mid=(l+r)>>1; spread(x);
if(ql<=mid) upd(ls,l,mid,ql,qr,w);
if(qr>mid) upd(rs,mid+1,r,ql,qr,w);
pushup(x);
}
inline int qry(int x,int l,int r,int ql,int qr){
if(l>=ql and r<=qr) return tr[x].w;
int mid=(l+r)>>1,res=0; spread(x);
if(ql<=mid) res+=qry(ls,l,mid,ql,qr);
if(qr>mid) res+=qry(rs,mid+1,r,ql,qr);
pushup(x); return res;
}
#undef ls
#undef rs
}A,B;
inline void sch(int u){
dep[u]=dep[fa[u]]+1;
if(!lson[u]) return siz[u]=1,void();
int &x=lson[u],&y=rson[u];
sch(x),siz[u]+=siz[x],sch(y),siz[u]+=siz[y];
if(le[x]>le[y]) swap(x,y);
le[u]=le[x],ri[u]=ri[y];
hson[u]=(siz[x]>siz[y] ? x : y);
}
inline void dfs(int u,int high){
rk[dfn[u]=++cnt]=u,tp[u]=high;
if(u==lson[fa[u]]) A.opd(1,1,m,dfn[u],siz[rson[fa[u]]]);
if(u==rson[fa[u]]) B.opd(1,1,m,dfn[u],siz[lson[fa[u]]]);
if(!hson[u]) return ; dfs(hson[u],high);
dfn[lson[u]] ? dfs(rson[u],rson[u]) : dfs(lson[u],lson[u]);
}
auto update=[](int x,int y,int w)->void{
x=id[x-1],y=id[y+1];
while(tp[x]^tp[y]){
if(dep[tp[x]]>dep[tp[y]]) A.upd(1,1,m,dfn[tp[x]],dfn[x],w),x=fa[tp[x]];
else B.upd(1,1,m,dfn[tp[y]],dfn[y],w),y=fa[tp[y]];
}
int z=(dep[x]>dep[y] ? y : x);
if(x^z) A.upd(1,1,m,dfn[z]+1,dfn[x],w);
if(y^z) B.upd(1,1,m,dfn[z]+1,dfn[y],w);
x=dfn[lson[z]],A.upd(1,1,m,x,x,-w);
y=dfn[rson[z]],B.upd(1,1,m,y,y,-w);
};
auto query=[](int x,int y,int res=0)->int{
x=id[x-1],y=id[y+1];
while(tp[x]^tp[y]){
if(dep[tp[x]]>dep[tp[y]]){
res+=A.qry(1,1,m,dfn[tp[x]],dfn[x]),x=fa[tp[x]];
}
else res+=B.qry(1,1,m,dfn[tp[y]],dfn[y]),y=fa[tp[y]];
}
int z=(dep[x]>dep[y] ? y : x);
if(x^z) res+=A.qry(1,1,m,dfn[z]+1,dfn[x]);
if(y^z) res+=B.qry(1,1,m,dfn[z]+1,dfn[y]);
x=dfn[lson[z]],res-=A.qry(1,1,m,x,x);
y=dfn[rson[z]],res-=B.qry(1,1,m,y,y);
return res;
};
signed main(){
File(pigeons);
n=read(),ops=read(),m=n; int x,y;
for(int i=1;i<=n;i++) le[i]=i,ri[i]=i,id[i]=i;
for(int i=2;i<=n;i++){
x=read(),y=read(),m++;
fa[x]=m,fa[y]=m,lson[m]=x,rson[m]=y;
}
for(int i=1;i<=m;i++) if(!fa[i]) { rt=i; break; }
fa[rt]=++m,rson[m]=rt,rt=m,lson[m]=m+1,fa[++m]=rt,id[0]=m;
fa[rt]=++m,lson[m]=rt,rt=m,rson[m]=m+1,fa[++m]=rt,id[n+1]=m;
sch(rt),dfs(rt,rt); int l,r,w;
// for(int i=1;i<=m;i++) cout<<lson[i]<<' '<<rson[i]<<'\n'; puts("");
while(ops--){
if(read()&1) l=read(),r=read(),w=read(),update(l,r,w);
else l=read(),r=read(),printf("%lld\n",query(l,r));
}
exit(0);
}