前言
music
《铃芽之旅》du du du du du du du du du du du du du du du dudu du du du du du du du du du du du du du du dudu du du du du du du du du du du du du du du dudu du du du du du du du du du du du du du du du于 你的生命之中红与蓝的线缠绕交错在 心间划上最后一笔勾勒出你的脉络那 随风飘荡的声音 从不曾被吹散片刻是 藏在心中的话 想对你说却还没能说人生啊 短暂如花微风啊 拂过脸颊星光啊 照谁的家我们是 宇宙一刹别再问 别再问 这样的我 为什么哭着眼泪替我诉说意义是你 意义是我意义总是 难以追寻的是我们相遇过 谁奋力呐喊着却吼不破命运的壳只能是你 只能由你触碰双手轻轻唤醒我沉睡千年的心搏意义是你 意义是我意义是否 最终跨越呢相隔时空的你我是愚昧又如何 是丑恶又如何 是望着前方正确的因果是想与你携手走过如今我已想不起曾经珍惜的回忆却似有万千言语深深埋葬在我心底或许就这样吧 或许就这样了还有什么遗憾的 我已交付所有的自己或许就这样吧 或许就这样了多么想让你听见这颗破碎又顽强的心只想靠近你别再问 别再问 这样的我 为什么哭着眼泪替我诉说意义是你 意义是我 意义总是 难以追寻的是我们相遇过 谁奋力呐喊着却吼不破命运的壳只能是你只能由你触碰双手轻轻唤醒我沉睡千年的心搏意义是你 意义是我意义是否 最终跨越呢相隔时空的你我是愚昧又如何 是丑恶又如何是望着前方 正确的因果是想与你携手走过
今天中午打电话我妈告诉我遇到诈骗了,诈骗的不知道从哪儿弄来我的短信给我妈发消息交钱,不过我这辈子没用过短信,再说我有事儿肯定打电话,最主要的是我从来没朝我妈要过钱,所以我妈一眼看出来是诈骗了。
但是挺离谱的诈骗的为啥会搞到我手机号还能知道我妈是谁还能知道我是学 OI 的?
T1 赛时不知道贪心是对的,奔着随机数据去的结果 A 了;T2 忘初始化保龄了;T4 没开 long long(开了,但是不知道啥时候给删了)挂了 35。
明天不想打了呜呜呜,还没打板子呢,但是如果明天不打今天可能就是最后一场了。
T1 flandre
贪心的发现一定是优先选大的,然后肯定是把小的排在前面。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=1e6+10,mx=1e6;
template<typename Tp> inline void read(Tp&x)
{x=0;register bool z=true;register char a=getchar_unlocked();for(;!isdigit(a);a=getchar_unlocked()) if(a=='-') z=0;for(;isdigit(a);a=getchar_unlocked()) x=(x<<1)+(x<<3)+(a^48);x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,tot,top,a[N],pos[N],sta[N]; ll k,ans,sum; vector<int>e[N<<1];
signed main()
{freopen("flandre.in","r",stdin),freopen("flandre.out","w",stdout);read(n,k);for(int i=1;i<=n;i++) read(a[i]),e[a[i]+mx].push_back(i);for(int i=mx;~i;i--) if(!e[i+mx].empty()){ans+=1ll*e[i+mx].size()*(i+k*m),m+=e[i+mx].size();for(int j:e[i+mx]) pos[++tot]=j;}sum=ans; for(int i=-1,tmp=0;i>=-mx;i--,tmp=0) if(!e[i+mx].empty()){for(int j=1;j<=e[i+mx].size();j++) if(sum+j*(k*m+i)>ans){for(int h=1;h<=top;h++) pos[++tot]=sta[h];for(int h=tmp;h<j;h++) pos[++tot]=e[i+mx][h];ans=sum+j*(k*m+i),tmp=j,top=0;}for(int j=tmp;j<e[i+mx].size();j++) sta[++top]=e[i+mx][j];sum+=e[i+mx].size()*(i+k*m),m+=e[i+mx].size();}write(ans,tot),puts(""),reverse(pos+1,pos+1+tot);for(int i=1;i<=tot;i++) write(pos[i]),putchar_unlocked(' ');
}
T2 meirin
往数据结构上想了,实际上是道数学题。
考虑把式子拆开,这是简单的,有很多种方式可以把他拆成单词 \(O(n)\) 的,但是需要把他拆成修改 \(O(1)\sim O(\log)\) 的。
发现 \(a_i\) 始终不变,考虑把 \(a_i\) 当成系数拎出来,转换后有:
\(sum_i\) 表示前缀和,发现转换为了 \(b_i\) 系数的形式,于是就可以直接算贡献了。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=5e5+10,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{x=0;register bool z=true;register char a=getchar_unlocked();for(;!isdigit(a);a=getchar_unlocked()) if(a=='-') z=0;for(;isdigit(a);a=getchar_unlocked()) x=(x<<1)+(x<<3)+(a^48);x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,ans,a[N],b[N];
inline int mod(int x,int y) {return (x+=y)>=P?x-P:x;}
signed main()
{freopen("meirin.in","r",stdin),freopen("meirin.out","w",stdout);read(n,m);for(int i=1,x;i<=n;i++) read(x),a[i]=mod(a[i-1],mod(x,P));for(int i=1;i<=n;i++) a[i]=mod(a[i-1],a[i]);for(int i=1,x;i<=n;i++){b[i]=mod(1ll*mod(a[n],P-a[i-1])*i%P,P-1ll*a[i-1]*(n-i+1)%P);read(x),ans=mod(ans,1ll*b[i]*mod(x,P)%P),b[i]=mod(b[i-1],b[i]);}for(int l,r,x;m;m--){read(l,r,x);write(ans=mod(ans,1ll*mod(b[r],P-b[l-1])*mod(x,P)%P)),puts("");}
}
T3 sakuya
考虑统计边 \((x,y)\) 出现的次数,断开这条边树会分成两部分,这条边被计算当且仅当相邻的两点分别在两部分中,那么这部分可以用树形 DP 做了。
考虑两点相邻的概率,用捆绑法求出两点相邻的概率为 \(\dfrac{2(m-1)!}{m!}=\dfrac{2}{m}\)。
加贡献的时候直接根据求出的 DP 加就可以了。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=5e5+10,P=998244353;
template<typename Tp> inline void read(Tp&x)
{x=0;register bool z=true;register char a=getchar_unlocked();for(;!isdigit(a);a=getchar_unlocked()) if(a=='-') z=0;for(;isdigit(a);a=getchar_unlocked()) x=(x<<1)+(x<<3)+(a^48);x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,tot,ans,f[N],sz[N]; ll inv; int head[N],nxt[N<<1],to[N<<1],w[N<<1];
inline int mod(int x,int y) {return (x+=y)>=P?x-P:x;}
inline int qpow(ll a,int b)
{ll res=1; for(;b;(a*=a)%=P,b>>=1) (b&1)&&((res*=a)%=P); return res;}
inline void add(int x,int y,int z)
{nxt[++tot]=head[x],to[tot]=y,w[tot]=z,head[x]=tot;}
inline void dfs1(int x,int t)
{for(int i=head[x],y;y=to[i];i=nxt[i]) if(y!=t) dfs1(y,x),sz[x]+=sz[y];}
inline void dfs2(int x,int t)
{f[t]=mod(f[t],1ll*sz[x]*(m-sz[x])%P);for(int i=head[x],y,tmp;y=to[i];i=nxt[i]) if(y!=t){f[y]=mod(f[y],tmp=1ll*sz[y]*(m-sz[y])%P);ans=mod(ans,1ll*tmp*w[i]%P),dfs2(y,x);}
}
signed main()
{freopen("sakuya.in","r",stdin),freopen("sakuya.out","w",stdout);read(n,m),inv=qpow(m,P-2)*2%P;for(int i=1,x,y,z;i<n;i++) read(x,y,z),add(x,y,z),add(y,x,z);for(int i=1,x;i<=m;i++) read(x),sz[x]=1; dfs1(1,0),dfs2(1,0),read(m);for(int x,k;m;m--,write(ans*inv%P),puts(""))read(x,k),ans=mod(ans,1ll*f[x]*k%P);
}
T4 红楼 ~ Eastern Dream
已经把根号分治写脸上了,问题在于怎么分别处理。
对于 \(x\le \sqrt n\) 的因为这种点最多只有 \(\sqrt n\) 个,所以直接算即可。
对于 \(x>\sqrt n\) 的,直接线段树会多个 \(\log\) 过不去,考虑序列分块加差分,从而做到每个块 \(O(1)\) 更新 \(O(\sqrt n)\) 查询,维护差分的方式和树状数组维护区间改区间查相同。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=2e5+10,M=300,L=1000;
template<typename Tp> inline void read(Tp&x)
{x=0;register bool z=true;register char a=getchar_unlocked();for(;!isdigit(a);a=getchar_unlocked()) if(a=='-') z=0;for(;isdigit(a);a=getchar_unlocked()) x=(x<<1)+(x<<3)+(a^48);x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,len,vl[N],vr[N],pos[N]; ll ans,a[N],b[N],c[N],s1[L],s2[L],d[M][M];
inline void add(int l,int r,int k)
{c[l]+=k,s1[pos[l]]+=k,s2[pos[l]]+=1ll*(vr[pos[l]]-l+1)*k;c[++r]-=k,s1[pos[r]]-=k,s2[pos[r]]-=1ll*(vr[pos[r]]-r+1)*k;
}
inline ll ask1(int x,int y) {return ~y?(y/x)*b[x]+d[x][y%x]:0;}
inline ll ask2(int l,int r)
{ll res=0; int x=pos[l],y=pos[r];for(int i=1;i<x;i++) res+=s1[i]*(r-l+1);for(int i=vl[x];i<l;i++) res+=c[i]*(r-l+1);if(x==y) {for(int i=l;i<=r;i++) res+=c[i]*(r-i+1); return res;}for(int i=l;i<=vr[x];i++) res+=c[i]*(r-i+1);for(int i=x+1;i<y;i++) res+=s1[i]*(r-vr[i])+s2[i];for(int i=vl[y];i<=r;i++) res+=c[i]*(r-i+1); return res;
}
signed main()
{freopen("scarlet.in","r",stdin),freopen("scarlet.out","w",stdout);read(n,m),len=max(1,(int)sqrt(n)/2);for(int i=1;i<=n;i++) read(a[i]),a[i]+=a[i-1],pos[i]=(i-1)/len+1;for(int i=1;i<=pos[n];i++) vl[i]=vr[i-1]+1,vr[i]=min(n,i*len);for(int op,x,y,k;m;m--){read(op,x,y); if(op&1){read(k),y=min(x-1,y); if(x<=len){b[x]+=1ll*k*(y+1);for(int i=0;i<=y;i++) d[x][i]+=1ll*(i+1)*k;for(int i=y+1;i<x;i++) d[x][i]+=1ll*(y+1)*k;}else for(int i=1;i<=n;i+=x) add(i,min(n,i+y),k); continue;}for(int i=1;i<=len;i++) ans+=ask1(i,y-1)-ask1(i,x-2);write(ans+a[y]-a[x-1]+ask2(x,y)),puts(""),ans=0;}
}