【CSP-S 2019题解】
之后可以说半条腿退役了
如果没那一个失误的话还有救
感觉现在对的感情也挺复杂的
有些东西自己也还没想明白
Day1
模拟即可
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline ull readu(){
char ch=gc();
ull res=0;
while(!isdigit(ch))ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
ull k;
int n,ans[100];
void solve(int pos,ull ret){
if(pos==1){
ans[pos]=ret;
return;
}
ull mid=1;
mid=mid<<(pos-1);
mid-=1;
if(ret<=mid){
ans[pos]=0;solve(pos-1,ret);return;
}
else{
ans[pos]=1;
solve(pos-1,mid-ret+mid+1);
return;
}
}
int main(){
freopen("code.in","r",stdin);
freopen("code.out","w",stdout);
n=read(),k=readu();
solve(n,k);
for(int i=n;i;i--)cout<<ans[i];
return 0;
}
考场太严重了
不知道为什么这傻逼题就是没想明白
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline void readstring(char *s){
int top=0;
char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
}
cs int N=500005;
char s[N];
int fa[N],pf[N];
int n;
ll anc[N];
vector<int> e[N];
void dfs(int u){
pf[u]=pf[fa[u]];
if(s[u]=='(')pf[u]=u;
else if(pf[u]>0){
anc[u]=anc[fa[pf[u]]]+1;
pf[u]=pf[fa[pf[u]]];
}
for(int &v:e[u])dfs(v);
}
void dfs2(int u){
for(int &v:e[u]){
anc[v]+=anc[u];
dfs2(v);
}
}
int main(){
#ifdef Stargazer
freopen("lx.cpp","r",stdin);
#endif
n=read();
readstring(s);
for(int i=2;i<=n;i++)fa[i]=read(),e[fa[i]].pb(i);
dfs(1),dfs2(1);
ll ret=0;
for(int i=1;i<=n;i++)ret^=1ll*i*anc[i];
cout<<ret;
}
不会
先无视的条件,出总方案
然后容斥用背包算方案
只需要记使用这个食材和没使用的差即可
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=998244353;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){return (a-=b)<0?(a+mod):a;}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){(a-=b)<0?(a+=mod):0;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
cs int N=105,M=2005,L=103;
char xxx;
int g[N][N],s[N],a[N][M],f[N][2*N];
int n,m;
char yyy;
inline int calc(int p){
f[0][L]=1;
for(int i=1;i<=n;i++){
for(int j=L-i;j<=L+i;j++){
f[i][j]=f[i-1][j];
if(j)Add(f[i][j],mul(f[i-1][j-1],a[i][p]));
Add(f[i][j],mul(f[i-1][j+1],dec(s[i],a[i][p])));
}
}
int res=0;
for(int k=L+1;k<=L+n;k++)
Add(res,f[n][k]);
return res;
}
int main(){
freopen("meal.in","r",stdin);
freopen("meal.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
a[i][j]=read();
Add(s[i],a[i][j]);
}
}
g[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=i;j++){
Add(g[i][j],g[i-1][j]);
if(j)Add(g[i][j],mul(g[i-1][j-1],s[i]));
}
int res=0;
for(int i=1;i<=n;i++)Add(res,g[n][i]);
for(int i=1;i<=m;i++){
memset(f,0,sizeof(f));
Dec(res,calc(i));
}
cout<<res<<'\n';
return 0;
}
如果有结论的话回来看证明也挺显然的
但就是没想到
可以直接看毛爷爷的题解
感性伪 证明其实可以考虑把一个序列分成递增的2段
那么一定是在位置满足且
切开
那么也就是说分界点一定要尽量靠后
然后单调队列找分解点即可
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll unsigned long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=40000005,M=100005;
char xxx;
int n,type,l[M],r[M],p[M],b[N],q[N],pre[N],hd,tl;
ll a[N];
char yyy;
void write(__int128 x){
if(x>9)write(x/10);
putchar((x%10)+'0');
}
inline void getans(){
__int128 ret=0;
for(int i=n;i;i=pre[i]){
ret+=(__int128)(a[i]-a[pre[i]])*(a[i]-a[pre[i]]);
}
write(ret);
}
int main(){
n=read(),type=read();
if(type==0){
for(int i=1;i<=n;i++)a[i]=read()+a[i-1];
}
else{
ll x=read(),y=read(),z=read();int m;cs ll bas=(1<<30)-1;
b[1]=read(),b[2]=read(),m=read();
for(int i=1;i<=m;i++)p[i]=read(),l[i]=read(),r[i]=read();
for(int i=3;i<=n;i++)b[i]=(x*b[i-1]+y*b[i-2]+z)&bas;
for(int i=1,j=1;i<=n;i++){
if(i>p[j])j++;
a[i]=(b[i]%(r[j]-l[j]+1))+l[j];
}
for(int i=1;i<=n;i++)a[i]+=a[i-1];
}
for(int i=1;i<=n;i++){
while(hd<tl&&(a[q[hd+1]]*2-a[pre[q[hd+1]]])<=a[i])hd++;
pre[i]=q[hd];
while(hd<=tl&&(a[q[tl]]*2-a[pre[q[tl]]])>=(a[i]*2-a[pre[i]]))tl--;
q[++tl]=i;
}
getans();
return 0;
}
考场已经想出做法了但觉得时间不够为了保险就没去写
直接考虑一个点会有多少边对其有贡献
分成三个部分考虑:
到根的链上的,到根链上点的其他子树的,子树内的
记子树内最大的为,一条边断开后子树内的为
到根链上的需要满足
即
其他子树的即
对于子树内需要考虑是哪颗子树
也可以做但比较麻烦
一个方法是以重心做根
那么对于重心以外的点就都不需要考虑子树
对于重心只需要考虑最大的子树和其他子树两种情况即可
然后就完了
为什么我考场不去写啊,傻逼透了
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=300005;
int n;
int rt,siz[N],mc[N];
ll ans;
vector<int> e[N];
struct bit{
int tr[N];
#define lb(x) (x&(-x))
inline void clear(){
memset(tr,0,sizeof(tr));
}
inline void update(int p,int k){
for(;p<=n;p+=lb(p))tr[p]+=k;
}
inline int ask(int p,int res=0){
for(;p>0;p-=lb(p))res+=tr[p];
return res;
}
inline int query(int l,int r){
return ask(r)-ask(l-1);
}
}s1,s2;
void dfs1(int u,int fa){
siz[u]=1;
bool fg=1;
for(int &v:e[u]){
if(v==fa)continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>(n>>1))fg=0;
}
if(n-siz[u]>(n>>1))fg=0;
if(fg)rt=u;
}
void dfs2(int u,int fa){
siz[u]=1,mc[u]=0;
for(int &v:e[u]){
if(v==fa)continue;
dfs2(v,u);
siz[u]+=siz[v];
chemx(mc[u],siz[v]);
}
}
void colc(int u,int fa,int k){
s1.update(siz[u],k);
for(int &v:e[u]){
if(v==fa)continue;
colc(v,u,k);
}
}
int cnt;
void dfs3(int u,int fa,int lim){
s2.update(siz[u],1);
ans+=1ll*u*(s1.query(n-2*siz[u],n-2*mc[u])+s2.query(2*mc[u],2*siz[u]));
if(siz[u]<=lim)ans+=rt,cnt++;
for(int &v:e[u]){
if(v==fa)continue;
dfs3(v,u,lim);
}
s2.update(siz[u],-1);
}
inline void solve(){
s1.clear(),s2.clear();
ans=rt=cnt=0,n=read();
for(int u,v,i=1;i<n;i++){
u=read(),v=read();
e[u].pb(v),e[v].pb(u);
}
dfs1(1,0);
dfs2(rt,0);
int mx=0,semx=0;
for(int &v:e[rt]){
if(siz[v]>siz[mx])semx=mx,mx=v;
else if(siz[v]>siz[semx])semx=v;
colc(v,rt,1);
}
for(int &v:e[rt]){
colc(v,rt,-1);
if(v==mx)dfs3(v,rt,n-2*siz[semx]);
else dfs3(v,rt,n-2*siz[mx]);
colc(v,rt,1);
}
cout<<ans<<'\n';
for(int i=1;i<=n;i++)e[i].clear();
}
int main(){
int T=read();
while(T--)solve();
}