九下三月中旬日记
3.11
闲话
- @wkh2008 和 @lty_ylzsx 被 \(miaomiao\) 从 \(1\) 机房赶到 \(3\) 机房了。
- 不知道为啥 \(field\) 来催了下改模拟赛的题,可能为了缓解尴尬(?)。
做题纪要
tgHZOJ 2893. 混乱邪恶
- 详见 初三奥赛模拟测试1 T3 混乱邪恶 。
luogu P1412 经营与开发
-
发现顺序枚举存在后效性,考虑倒序枚举。
-
设 \(f_{i}\) 表示截止到第 \(i\) 个星球时 \(1\) 能力值能获得的最大金钱,状态转移方程为 \(f_{i}= \begin{cases} \max(f_{i+1},(1-0.01k)f_{i+1}+x_{i}) & type_{i}=1 \\ \max(f_{i+1},(1+0.01c)f_{i+1}-x_{i}) & type_{i}=2 \end{cases}\) 。
点击查看代码
int pd[200000]; double x[200000],f[200000]; int main() { int n,i; double k,c,w; cin>>n>>k>>c>>w; for(i=1;i<=n;i++) { cin>>pd[i]>>x[i]; } for(i=n;i>=1;i--) { f[i]=max(f[i+1],(pd[i]==1)?f[i+1]*(1-0.01*k)+x[i]:f[i+1]*(1+0.01*c)-x[i]); } printf("%.2lf\n",f[1]*w); return 0; }
3.12
闲话
- 貌似调考成绩算回原班级,已经在想象调考后以前课任老师上来 \(D\) 人了。
做题纪要
[ABC343G] Compress Strings
-
多倍经验: CF25E Test
-
由于 \(\sum\limits_{i=1}^{n} |S_{i}|\) 极大且不需要记录路径,所以 luogu P2322 [HNOI2006] 最短母串问题 的枚举所有可能的字符串 \(T\) 进行判断不可做。
-
设 \(f_{i,j}\) 表示当“字符串包含状态”对应的二进制数为 \(i\) 时,且结尾为 \(j\) 时的最小长度,状态转移方程为 \(f_{i,j}= \min\limits_{j \ne k,(i \gg k) \And 1 \ne 0}^{} \{f_{i-(1 \ll j),k}-g_{k,j}+|S_{j}| \}\) ,其中 \(g_{k,j}\) 表示 \(S_{k}\) 的后缀和 \(S_{j}\) 的前缀匹配的最长长度,使用 \(KMP\) 维护即可。
-
注意去重和删去在其他字符串中已被包含的字符串。
点击查看代码
int nxt[200010],f[(1<<22)+10][22],g[22][22]; string s[22],ss[22],t; int main() { int m,n=0,ans=0x7f7f7f7f,flag,i,j,k,x,y; cin>>m; memset(f,0x3f,sizeof(f)); for(i=0;i<=m-1;i++) { cin>>ss[i]; } sort(ss+0,ss+m); m=unique(ss+0,ss+m)-ss; for(i=0;i<=m-1;i++) { flag=0; for(j=0;j<=m-1;j++) { if(i!=j&&ss[j].find(ss[i])!=string::npos) { flag=1; break; } } if(flag==0) { s[n]=ss[i]; n++; } } for(x=0;x<=n-1;x++) { for(y=0;y<=n-1;y++) { if(x!=y) { t=' '+s[y]+'#'+s[x]; for(i=2,nxt[1]=j=0;i<t.size();i++) { while(j>=1&&t[i]!=t[j+1]) { j=nxt[j]; } j+=(t[i]==t[j+1]); nxt[i]=j; } g[x][y]=nxt[t.size()-1]; } } } for(i=0;i<=n-1;i++) { f[(1<<i)][i]=s[i].size(); } for(i=0;i<=(1<<n)-1;i++) { for(j=0;j<=n-1;j++) { if((i>>j)&1) { for(k=0;k<=n-1;k++) { if(j!=k&&((i>>k)&1)) { f[i][j]=min(f[i][j],f[i-(1<<j)][k]-g[k][j]+(int)s[j].size()); } } } } } for(i=0;i<=n-1;i++) { ans=min(ans,f[(1<<n)-1][i]); } cout<<ans<<endl; return 0; }
3.13
闲话
- 下午到机房的时候,发现电脑在今天上午 \(11:30\) 的时候死机了,浏览记录多了个 tgHZOJ 。
- 因和 \(miaomiao\) 交涉失败,下午要去博艺馆开中考百日誓师大会,占了下午第 \(8,9\) 节课。因有家长和老师参与,故 \(25,26,27\) 班只能坐在过道。洗脑痕迹明显。
- 开完大会说让回班让班主任开百日誓师班会,但现班主任出差了,代班主任连上周日的班会都没开,索性直接来机房了。
- 晚上回班后发现应该开班会的课改成公自了,赌赢了。
做题纪要
luogu P3214 [HNOI2011] 卡农
-
简化题意
- 给定 \(n,m\) 。求在集合 \(S= \{ 1,2,3, \dots ,n \}\) 中选出 \(m\) 个子集,且这 \(m\) 个子集满足以下三个性质的无序集合方案数。
- 性质 \(1\) :选出的 \(m\) 个子集中每个子集都不能为空。
- 性质 \(2\) :选出的 \(m\) 个子集中不存在两个相同的子集。
- 性质 \(3\) :选出的 \(m\) 个子集中 \(1 \sim n\) 的每个数的总出现次数必须是偶数。
- 给定 \(n,m\) 。求在集合 \(S= \{ 1,2,3, \dots ,n \}\) 中选出 \(m\) 个子集,且这 \(m\) 个子集满足以下三个性质的无序集合方案数。
-
设 \(f_{i}\) 表示到当前枚举到第 \(i\) 个子集时,满足三个性质的有序集合方案数,状态转移方程为 \(f_{i}= \begin{cases} 1 & i=0 \\ A_{2^{n}-1}^{i-1}-f_{i-1}-f_{i-2} \times A_{i-1}^{1} \times A_{2^{n}-1-(i-2)}^{1} & i \ne 0 \end{cases}\) 。
- 假设当前已确认了前 \(i-1\) 个子集,且前 \(i-1\) 个子集满足三个性质。
- 加上第 \(i\) 个子集后满足性质 \(3\) 的共有 \(A_{2^{n}-1}^{i-1}\) 种方案。
- 从二进制下异或和的角度分析,该结论显然。
- 加上第 \(i\) 个子集后满足性质 \(3\) ,但不满足性质 \(1\) ,即第 \(i\) 个子集为空的共有 \(f_{i-1}\) 种方案。
- 加上第 \(i\) 个子集后满足性质 \(3\) ,但不满足性质 \(2\) ,即第 \(i\) 个子集在前 \(i-1\) 个子集中已经出现过一次的共有 \(f_{i-2} \times A_{i-1}^{1} \times A_{2^{n}-1-(i-2)}^{1}\) 种方案。
-
由 \(A_{n}^{m} \times \frac{1}{n-m+1}=A_{n}^{m-1}\) ,有 \(A_{n}^{m}=A_{n}^{m-1} \times (n-m+1)\) 。
-
最终,有 \(\frac{f_{m}}{A_{m}^{m}}\) 即为所求。
点击查看代码
const ll p=100000007; ll inv[1000010],jc[1000010],jc_inv[1000010],a[1000010],f[1000010]; void A1(ll n,ll m,ll p) { a[0]=1; for(ll i=1;i<=m;i++) { a[i]=a[i-1]*(n-i+1)%p; } } ll A2(ll n,ll m,ll p) { return (n>=m&&n>=0&&m>=0)?((m==1)?n:jc[n]*jc_inv[n-m]%p):0; } ll qpow(ll a,ll b,ll p) { ll ans=1; while(b>0) { if(b&1) { ans=ans*a%p; } b>>=1; a=a*a%p; } return ans; } int main() { ll n,m,sum,i; cin>>n>>m; sum=(qpow(2,n,p)-1+p)%p; A1(sum,m,p); inv[1]=1; jc[0]=jc_inv[0]=jc[1]=jc_inv[1]=1; for(i=2;i<=max(n,m);i++) { inv[i]=(p-p/i)*inv[p%i]%p; jc[i]=jc[i-1]*i%p; jc_inv[i]=jc_inv[i-1]*inv[i]%p; } f[0]=1; for(i=1;i<=m;i++) { f[i]=((a[i-1]-f[i-1]+p)%p-(f[i-2]*A2(i-1,1,p)%p)*A2(sum-(i-2),1,p)%p+p)%p; } cout<<f[m]*qpow(A2(m,m,p),p-2,p)%p<<endl; return 0; }
luogu P4884 多少个 1?
-
\(\begin{matrix}n 个 1 \\ \overbrace{11 \dots 1}\end{matrix} \equiv b \pmod{p}\) 等价于 \(\frac{10^{n}-1}{9} \equiv b \pmod{p}\) ,移项得 \(10^{n} \equiv (9b+1) \pmod{p}\) 。
点击查看代码
#define ll __int128_t ll read() { ll x=0,f=1; char c=getchar(); while(c>'9'||c<'0') { if(c=='-') { f=-1; } c=getchar(); } while('0'<=c&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x>9) { write(x/10); } putchar((x%10)+'0'); } ll qpow(ll a,ll b,ll p) { ll ans=1; while(b>0) { if(b&1) { ans=ans*a%p; } b>>=1; a=a*a%p; } return ans; } ll bsgs(ll a,ll b,ll p) { if(1%p==b%p) { return 0; } else { map<ll,ll>vis; ll k=sqrtl(p)+1,i,sum; for(i=0;i<=k-1;i++) { vis[b*qpow(a,i,p)%p]=i; } a=qpow(a,k,p); for(i=0;i<=k;i++) { sum=qpow(a,i,p); if(vis.find(sum)!=vis.end()) { if(i*k-vis[sum]>=0) { return i*k-vis[sum]; } } } return -1; } } int main() { ll b,p; b=read(); p=read(); write(bsgs(10,9*b+1,p)); return 0; }
luogu P4454 [CQOI2018] 破解D-H协议
-
由 原根 定义,有 \(\gcd(g,p)=1\) 。
点击查看代码
#define ll __int128_t ll read() { ll x=0,f=1; char c=getchar(); while(c>'9'||c<'0') { if(c=='-') { f=-1; } c=getchar(); } while('0'<=c&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x>9) { write(x/10); } putchar((x%10)+'0'); } ll qpow(ll a,ll b,ll p) { ll ans=1; while(b>0) { if(b&1) { ans=ans*a%p; } b>>=1; a=a*a%p; } return ans; } ll bsgs(ll a,ll b,ll p) { if(1%p==b%p) { return 0; } else { map<ll,ll>vis; ll k=sqrtl(p)+1,i,sum; for(i=0;i<=k-1;i++) { vis[b*qpow(a,i,p)%p]=i; } a=qpow(a,k,p); for(i=0;i<=k;i++) { sum=qpow(a,i,p); if(vis.find(sum)!=vis.end()) { if(i*k-vis[sum]>=0) { return i*k-vis[sum]; } } } return -1; } } int main() { ll g,p,n,a,b,i; g=read(); p=read(); n=read(); for(i=1;i<=n;i++) { a=read(); b=read(); write(qpow(a,bsgs(g,b,p),p)); cout<<endl; } return 0; }
3.14
闲话
- 早上到机房的时候,发现电脑在今天凌晨 \(2:10\) 的时候死机了,以后走的时候索性直接关机了。
- 回班的时候看见 \(miaomiao\) 坐在靠门的位置摆弄 \(NOI \ Linux \ 2.0\) ,但他为什么不坐在教师机的位置呢。
- \(miaomiao\) 下午 \(14:00 \sim 18:05\) 安排了一场模拟赛,可能以后都是周四有模拟赛。
- 下午 \(14:06\) 的时候 @jijidawang 才到机房,然后被 \(miaomiao\) \(D\) 了。
- 晚上代班主任说周五第一节课调到下午上,成功少了一节仅有 \(40min\) 的奥赛课。
做题纪要
luogu P5025 [SNOI2017] 炸弹
-
设 \([L_{i},R_{i}]\) 表示第 \(i\) 颗炸弹所能引爆的炸弹区间。
-
处理出第 \(i\) 颗炸弹的实际引爆半径 \(r_{i}'\) ,然后分别对左右端点进行转移即可。
点击查看代码
const ll p=1000000007; ll x[500010],r[500010],L[500010],R[500010]; int main() { ll n,ans=0,i; cin>>n; for(i=1;i<=n;i++) { cin>>x[i]>>r[i]; L[i]=R[i]=i; } for(i=1;i<=n;i++) { while(L[i]-1>=1&&x[i]-r[i]<=x[L[i]-1]) { r[i]=max(r[i],x[L[i]-1]+r[L[i]-1]-x[i]); L[i]=L[L[i]-1]; } } for(i=n;i>=1;i--) { while(R[i]+1<=n&&x[i]+r[i]>=x[R[i]+1]) { L[i]=min(L[i],L[R[i]+1]);//可能存在先炸右边得到的左端点比先炸左边得到的左端点更靠左 R[i]=R[R[i]+1]; } } for(i=1;i<=n;i++) { ans=(ans+(R[i]-L[i]+1)*i%p)%p; } cout<<ans<<endl; return 0; }
CF56E Domino Principle
-
将多米诺骨牌压倒转化为炸弹爆炸即可,注意只更新右端点。
点击查看代码
struct node { int x,r,L,R,id; }a[100010]; bool cmp1(node a,node b) { return a.x<b.x; } bool cmp2(node a,node b) { return a.id<b.id; } int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i].x>>a[i].r; a[i].r--; a[i].id=i; } sort(a+1,a+1+n,cmp1); for(i=1;i<=n;i++) { a[i].L=a[i].R=i; } for(i=n;i>=1;i--) { while(a[i].R+1<=n&&a[i].x+a[i].r>=a[a[i].R+1].x) { a[i].r=max(a[i].r,a[a[i].R+1].x+a[a[i].R+1].r-a[i].x); a[i].R=a[a[i].R+1].R; } } for(i=n;i>=1;i--) { while(a[i].R+1<=n&&a[i].x+a[i].r>=a[a[i].R+1].x) { a[i].R=max(a[i].R,a[a[i].R+1].R); } } sort(a+1,a+1+n,cmp2); for(i=1;i<=n;i++) { cout<<a[i].R-a[i].L+1<<" "; } return 0; }
LibreOJ 6277. 数列分块入门 1
-
维护整块的增量标记 \(add_{i}\) 即可。
-
块长取 \(\sqrt{n}\) 。
点击查看代码
ll a[50010],add[50010],L[50010],R[50010],pos[50010],klen,ksum; void init(ll n) { klen=sqrt(n); ksum=n/klen; for(ll i=1;i<=ksum;i++) { L[i]=R[i-1]+1; R[i]=min(R[i-1]+klen,n); } if(R[ksum]<n) { ksum++; L[ksum]=R[ksum-1]+1; R[ksum]=n; } for(ll i=1;i<=ksum;i++) { for(ll j=L[i];j<=R[i];j++) { pos[j]=i; } } } void update(ll l,ll r,ll val) { if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { a[i]+=val; } } else { for(ll i=l;i<=R[pos[l]];i++) { a[i]+=val; } for(ll i=pos[l]+1;i<=pos[r]-1;i++) { add[i]+=val; } for(ll i=L[pos[r]];i<=r;i++) { a[i]+=val; } } } ll ask(ll l) { return a[l]+add[pos[l]]; } int main() { ll n,pd,l,r,val,i; scanf("%lld",&n); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); } init(n); for(i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",&pd,&l,&r,&val); if(pd==0) { update(l,r,val); } else { printf("%lld\n",ask(r)); } } return 0; }
HDU1166 敌兵布阵
-
块长取 \(\sqrt{n}\) 。
点击查看代码
int a[50010],sum[50010],L[50010],R[50010],pos[50010],klen,ksum; void init(int n) { klen=sqrt(n); ksum=n/klen; for(int i=1;i<=ksum;i++) { L[i]=R[i-1]+1; R[i]=R[i-1]+klen; } if(R[ksum]<n) { ksum++; L[ksum]=R[ksum-1]+1; R[ksum]=n; } for(int i=1;i<=ksum;i++) { sum[i]=0; for(int j=L[i];j<=R[i];j++) { pos[j]=i; sum[i]+=a[j]; } } } void update(int l,int val) { a[l]+=val; sum[pos[l]]+=val; } int query(int l,int r) { int ans=0; if(pos[l]==pos[r]) { for(int i=l;i<=r;i++) { ans+=a[i]; } } else { for(int i=l;i<=R[pos[l]];i++) { ans+=a[i]; } for(int i=pos[l]+1;i<=pos[r]-1;i++) { ans+=sum[i]; } for(int i=L[pos[r]];i<=r;i++) { ans+=a[i]; } } return ans; } int main() { int t,n,l,r,i,j; char pd[10]; scanf("%d",&t); for(j=1;j<=t;j++) { scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&a[i]); } init(n); printf("Case %d:\n",j); while(scanf("%s",pd+1)) { if(pd[1]=='E') { break; } scanf("%d%d",&l,&r); if(pd[1]=='A') { update(l,r); } if(pd[1]=='S') { update(l,-r); } if(pd[1]=='Q') { printf("%d\n",query(l,r)); } } } return 0; }
LibreOJ 6280. 数列分块入门 4
-
维护整块的增量标记 \(add_{i}\) 即可。
-
块长取 \(\sqrt{n}\) 。
点击查看代码
ll a[50010],sum[50010],add[50010],L[50010],R[50010],pos[50010],klen,ksum; void init(ll n) { klen=sqrt(n); ksum=n/klen; for(ll i=1;i<=ksum;i++) { L[i]=R[i-1]+1; R[i]=R[i-1]+klen; } if(R[ksum]<n) { ksum++; L[ksum]=R[ksum-1]+1; R[ksum]=n; } for(ll i=1;i<=ksum;i++) { for(ll j=L[i];j<=R[i];j++) { pos[j]=i; sum[i]+=a[j]; } } } void update(ll l,ll r,ll val) { if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { a[i]+=val; } sum[pos[l]]+=val*(r-l+1); } else { for(ll i=l;i<=R[pos[l]];i++) { a[i]+=val; } sum[pos[l]]+=val*(R[pos[l]]-l+1); for(ll i=pos[l]+1;i<=pos[r]-1;i++) { add[i]+=val; } for(ll i=L[pos[r]];i<=r;i++) { a[i]+=val; } sum[pos[r]]+=val*(r-L[pos[r]]+1); } } ll query(ll l,ll r,ll p) { ll ans=0; if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { ans=(ans+a[i]%p)%p; } ans=(ans+(add[pos[l]]%p)*(r-l+1)%p)%p; } else { for(ll i=l;i<=R[pos[l]];i++) { ans=(ans+a[i]%p)%p; } ans=(ans+(add[pos[l]]%p)*(R[pos[l]]-l+1)%p)%p; for(ll i=pos[l]+1;i<=pos[r]-1;i++) { ans=((ans+sum[i]%p)%p+(add[i]%p)*(klen%p)%p)%p; } for(ll i=L[pos[r]];i<=r;i++) { ans=(ans+a[i]%p)%p; } ans=(ans+(add[pos[r]]%p)*(r-L[pos[r]]+1)%p)%p; } return ans; } int main() { ll n,pd,l,r,val,i; scanf("%lld",&n); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); } init(n); for(i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",&pd,&l,&r,&val); if(pd==0) { update(l,r,val); } else { printf("%lld\n",query(l,r,val+1)); } } return 0; }
UVA12003 Array Transformer
-
多倍经验:SP3261 RACETIME - Race Against Time | SP18185 GIVEAWAY - Give Away
-
对于在整块内找小于给出的数的所有元素个数,容易想到对块内元素进行排序,然后二分查找得到答案。
点击查看代码
ll a[50010],b[50010],L[50010],R[50010],pos[50010],klen,ksum; void init(ll n) { klen=sqrt(n); ksum=n/klen; for(ll i=1;i<=ksum;i++) { L[i]=R[i-1]+1; R[i]=R[i-1]+klen; } if(R[ksum]<n) { ksum++; L[ksum]=R[ksum-1]+1; R[ksum]=n; } for(ll i=1;i<=ksum;i++) { for(ll j=L[i];j<=R[i];j++) { pos[j]=i; } sort(b+L[i],b+R[i]+1); } } void update(ll l,ll val) { b[lower_bound(b+L[pos[l]],b+R[pos[l]]+1,a[l])-b]=val; a[l]=val; sort(b+L[pos[l]],b+R[pos[l]]+1); } ll query(ll l,ll r,ll val) { ll ans=0; if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { ans+=(a[i]<=val); } } else { for(ll i=l;i<=R[pos[l]];i++) { ans+=(a[i]<=val); } for(ll i=pos[l]+1;i<=pos[r]-1;i++) { ans+=lower_bound(b+L[i],b+R[i]+1,val)-b-L[i]; } for(ll i=L[pos[r]];i<=r;i++) { ans+=(a[i]<=val); } } return ans; } int main() { ll n,m,u,l,r,val,p,i; char pd; cin>>n>>m>>u; for(i=1;i<=n;i++) { cin>>a[i]; b[i]=a[i]; } init(n); for(i=1;i<=m;i++) { cin>>l>>r>>val>>p; update(p,u*query(l,r,val)/(r-l+1)); } for(i=1;i<=n;i++) { cout<<a[i]<<endl; } return 0; }
3.15
闲话
- @wkh2008 被 \(miaomiao\) 叫到机房学高一 \(whk\) 了。
- 吃完早饭 @Vsinger_洛天依 给我说 \(miaomiao\) 问他报不报 \(APIO\) ,他说报,然后 \(miaomiao\) 就把他报上去了,但 \(miaomiao\) 根本没和我们说这件事。
- 吃完晚饭后看见 \(field\) 领着 \(4,5\) 个 ZZ (女生居多)的在校园里面转,不知道是来干什么的。
- 晚上年级部说要改作息,早上从 \(6:50\) 起床改到了 \(6:20\) 起床了,多出来的 \(30min\) 分成了 \(20min\) 的早读和 \(10min\) 的课间(但实际上被早读占了)。
做题纪要
LibreOJ 6278. 数列分块入门 2
-
多倍经验: luogu P2801 教主的魔法
-
对于整块的修改操作,其相对大小顺序不变,故维护整块的增量标记 \(add_{i}\) 即可。
点击查看代码
ll a[50010],b[50010],add[50010],L[50010],R[50010],pos[50010],klen,ksum; void init(ll n) { klen=sqrt(n); ksum=n/klen; for(ll i=1;i<=ksum;i++) { L[i]=R[i-1]+1; R[i]=R[i-1]+klen; } if(R[ksum]<n) { ksum++; L[ksum]=R[ksum-1]+1; R[ksum]=n; } for(ll i=1;i<=ksum;i++) { for(ll j=L[i];j<=R[i];j++) { pos[j]=i; } sort(b+L[i],b+R[i]+1); } } void update(ll l,ll r,ll val) { if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { a[i]+=val; } for(ll i=L[pos[l]];i<=R[pos[l]];i++)//因是区间修改,所以直接复制过来即可 { b[i]=a[i]; } sort(b+L[pos[l]],b+R[pos[l]]+1); } else { for(ll i=l;i<=R[pos[l]];i++) { a[i]+=val; } for(ll i=L[pos[l]];i<=R[pos[l]];i++) { b[i]=a[i]; } sort(b+L[pos[l]],b+R[pos[l]]+1); for(ll i=pos[l]+1;i<=pos[r]-1;i++) { add[i]+=val; } for(ll i=L[pos[r]];i<=r;i++) { a[i]+=val; } for(ll i=L[pos[r]];i<=R[pos[r]];i++) { b[i]=a[i]; } sort(b+L[pos[r]],b+R[pos[r]]+1); } } ll query(ll l,ll r,ll val) { ll ans=0; if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { ans+=(a[i]+add[pos[l]]<val); } } else { for(ll i=l;i<=R[pos[l]];i++) { ans+=(a[i]+add[pos[l]]<val); } for(ll i=pos[l]+1;i<=pos[r]-1;i++) { ans+=lower_bound(b+L[i],b+R[i]+1,val-add[i])-b-L[i]; } for(ll i=L[pos[r]];i<=r;i++) { ans+=(a[i]+add[pos[r]]<val); } } return ans; } int main() { ll n,pd,l,r,val,i; scanf("%lld",&n); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); b[i]=a[i]; } init(n); for(i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",&pd,&l,&r,&val); if(pd==0) { update(l,r,val); } else { printf("%lld\n",query(l,r,val*val)); } } return 0; }
LibreOJ 6279. 数列分块入门 3
-
注意在找整块时把增量标记 \(add\) 加回来。
点击查看代码
ll a[100010],b[100010],add[100010],L[100010],R[100010],pos[100010],klen,ksum; void init(ll n) { klen=sqrt(n); ksum=n/klen; for(ll i=1;i<=ksum;i++) { L[i]=R[i-1]+1; R[i]=R[i-1]+klen; } if(R[ksum]<n) { ksum++; L[ksum]=R[ksum-1]+1; R[ksum]=n; } for(ll i=1;i<=ksum;i++) { for(ll j=L[i];j<=R[i];j++) { pos[j]=i; } sort(b+L[i],b+R[i]+1); } } void update(ll l,ll r,ll val) { if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { a[i]+=val; } for(ll i=L[pos[l]];i<=R[pos[l]];i++) { b[i]=a[i]; } sort(b+L[pos[l]],b+R[pos[l]]+1); } else { for(ll i=l;i<=R[pos[l]];i++) { a[i]+=val; } for(ll i=L[pos[l]];i<=R[pos[l]];i++) { b[i]=a[i]; } sort(b+L[pos[l]],b+R[pos[l]]+1); for(ll i=pos[l]+1;i<=pos[r]-1;i++) { add[i]+=val; } for(ll i=L[pos[r]];i<=r;i++) { a[i]+=val; } for(ll i=L[pos[r]];i<=R[pos[r]];i++) { b[i]=a[i]; } sort(b+L[pos[r]],b+R[pos[r]]+1); } } ll query(ll l,ll r,ll val) { ll ans=-0x7f7f7f7f; if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { ans=max(ans,(a[i]+add[pos[l]]<val)?a[i]+add[pos[l]]:-0x7f7f7f7f); } } else { for(ll i=l;i<=R[pos[l]];i++) { ans=max(ans,(a[i]+add[pos[l]]<val)?a[i]+add[pos[l]]:-0x7f7f7f7f); } for(ll i=pos[l]+1;i<=pos[r]-1;i++) { ans=max(ans,(lower_bound(b+L[i],b+R[i]+1,val-add[i])-b-1>=L[i])?b[lower_bound(b+L[i],b+R[i]+1,val-add[i])-b-1]+add[i]:-0x7f7f7f7f); } for(ll i=L[pos[r]];i<=r;i++) { ans=max(ans,(a[i]+add[pos[r]]<val)?a[i]+add[pos[r]]:-0x7f7f7f7f); } } return (ans==-0x7f7f7f7f)?-1:ans; } int main() { ll n,pd,l,r,val,i; scanf("%lld",&n); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); b[i]=a[i]; } init(n); for(i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",&pd,&l,&r,&val); if(pd==0) { update(l,r,val); } else { printf("%lld\n",query(l,r,val)); } } return 0; }
CF1153D Serval and Rooted Tree
- 详见 初三奥赛模拟测试2 T2 昌 。
3.16
闲话
- 上午第 \(5\) 节课课表写得是“公(A)”,然后 @lty_ylzsx 把“公()”擦了只剩下“A”,接着全班发出欢呼,我们就来机房了。
- 下午 \(miaomiao\) 称 \(3\) 机房电脑太差了,所以让我们搬到 \(4\) 机房了,顺便稍微收拾了下机房。 \(miaomiao\) 还 \(D\) 了下高二的,说我们别把机房整得乱得跟高二的一样。我坐在了 @Trump_ 的位置上。
- 在 \(4\) 机房发现了数个乒乓球排、羽毛球排,还有一个篮球。
- @jijidawang 请假回家了,但 \(miaoamiao\) 和我们不知道,误以为他消失了。
- 下午高二的放假了。
- \(4\) 机房有 \(3\) 台教师机, \(2\) 个键盘。貌似有一台能查是否有人改 \(IP\) 。接着高一改 \(IP\) 的事情就被教练发现了。
- 下午从厕所回机房的路上看见年级德育主任从教练办公室出来了,不知道他来干啥。
- 临吃饭的时候, \(miaomiao\) 称因为明天 luogu 有比赛,所以把我们明天下午旷周测的事情批了;接着我告诉 \(miaomiao\) 有 ABC ,然后他把我们晚上旷周测(一开始 \(miaomiao\) 以为我们非常热爱 \(whk\) ,所以是半节,后面 \(miaomiao\) 又反悔了 )的事情批了。
- 晚上来机房后, \(feifei\) 问我们为啥今晚上来机房了,我们给他说晚上有 ABC ,结果 \(feifei\) 问我们啥是 ABC 。
- 晚上 @wang54321 和 @HS_xh 因在打 ABC 时交流,被 \(feifei\) \(D\) 了。
做题纪要
luogu P4550 收集邮票
- 详见 初三奥赛模拟测试2 T1 南 。
LibreOJ 6089. 小 Y 的背包计数问题
- 详见 初三奥赛模拟测试2 T4 义 。
[ABC345A] Leftrightarrow
[ABC345B] Integer Division Returns
[ABC345C] One Time Swap
3.17
闲话
- 下午小孩哥在 \(3\) 机房听 \(miaomiao\) 讲高精度。
- 下午高二的返校了。在机房看见了 @User_Unauthorized 和 @Trump_ 来收拾书,他们貌似被发配到录播室补 whk 了。
做题纪要
luogu P10251 农场
luogu P10252 线性变换
tgHZOJ 2813. 起
- 详见 初三奥赛模拟测试2 T3 起 。
3.18
闲话
- 现班主任出差回来了。
- \(miaomiao\) 下午给我们启动了 HZOI2024 冲刺 NOIP2024 400pts 计划 。
做题纪要
3.19
- 下午到机房的时候发现 \(4\) 机房把 luogu 封了,其他机房反而把 luogu 开了,成功进入 vjudge 改变生活 时期。
闲话
做题纪要
luogu P10253 说唱
CF922E Birds
CF1628D1 Game on Sum (Easy Version)
3.20
闲话
- 下午到机房的时候,发现机房大部分电脑被重启了,我旁边的 \(Windows\) , @wkh2008 和 @K8He 的电脑幸免于难。
- @K8He 请假回家了, @wkh2008 被迫回班学 \(whk\) 了。
- 下午因我发出奇怪声音,被 \(miaomiao\) \(D\) 了。
做题纪要
2024年中国传媒大学程序设计大赛(同步赛)C 小红的 CUC
-
直接构造即可。
点击查看代码
int main() { int n,i; cin>>n; if(n>=3) { cout<<"CUC"; for(i=1;i<=n-3;i++) { cout<<"A"; } } else { cout<<"-1"<<endl; } return 0; }
LibreOJ 6281. 数列分块入门 5
-
多倍经验: luogu P4145 上帝造题的七分钟 2 / 花神游历各国 | SP2713 GSS4 - Can you answer these queries IV
-
观察到 \(\left\lfloor \sqrt{a_{i}} \right\rfloor\) 的下降速度极快。
-
类似 luogu P2898 [USACO08JAN] Haybale Guessing G 的思路。当 \(a_{i} \le 1\) 时,将第 \(i\) 棵树和第 \(i+1\) 棵树合并;否则不合并。
-
然后就转化成了单点修改,区间查询问题了。
点击查看代码
ll f[50010],a[50010],sum[50010],L[50010],R[50010],pos[50010],klen,ksum; ll find(ll x) { return (f[x]==x)?x:f[x]=find(f[x]); } void init(ll n) { klen=sqrt(n); ksum=n/klen; for(ll i=1;i<=ksum;i++) { L[i]=R[i-1]+1; R[i]=R[i-1]+klen; } if(R[ksum]<n) { ksum++; L[ksum]=R[ksum-1]+1; R[ksum]=n; } for(ll i=1;i<=ksum;i++) { for(ll j=L[i];j<=R[i];j++) { pos[j]=i; sum[i]+=a[j]; } } } void update(ll l,ll r) { for(ll i=l;i<=r;i=find(i+1)) { sum[pos[i]]+=sqrt(a[i])-a[i]; a[i]+=sqrt(a[i])-a[i]; f[i]=(a[i]<=1)?f[i+1]:f[i]; } } ll query(ll l,ll r) { ll ans=0; if(pos[l]==pos[r]) { for(ll i=l;i<=r;i++) { ans+=a[i]; } } else { for(ll i=l;i<=R[pos[l]];i++) { ans+=a[i]; } for(ll i=pos[l]+1;i<=pos[r]-1;i++) { ans+=sum[i]; } for(ll i=L[pos[r]];i<=r;i++) { ans+=a[i]; } } return ans; } int main() { ll n,pd,l,r,val,i; scanf("%lld",&n); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); f[i]=i; } f[n+1]=n+1; init(n); for(i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",&pd,&l,&r,&val); if(pd==0) { update(l,r); } else { printf("%lld\n",query(l,r)); } } return 0; }
2024年中国传媒大学程序设计大赛(同步赛)A 小苯的区间和疑惑
-
把 \([l,r]\) 拆成 \([l,i]\) 和 \([i,r]\) 即可,然后就转化为 luogu P1115 最大子段和 了,使用 \(DP\) 求解即可。
点击查看代码
ll a[200010][2],f[200010][2]; int main() { ll n,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i][0]; } for(i=1;i<=n;i++) { a[i][1]=a[n-i+1][0]; } for(i=1;i<=n;i++) { f[i][0]=max(f[i-1][0],0ll)+a[i][0]; f[i][1]=max(f[i-1][1],0ll)+a[i][1]; } for(i=1;i<=n;i++) { cout<<f[i][0]+f[n-i+1][1]-a[i][0]<<" "; } return 0; }
LibreOJ 6283. 数列分块入门 7
-
优先更新整块的乘量标记 \(mul_{i}\) 。
-
对散块进行修改时注意清空标记。
点击查看代码
const ll p=10007; ll a[100010],sum[100010],add[100010],mul[100010],L[100010],R[100010],pos[100010],klen,ksum; void init(ll n) { klen=sqrt(n); ksum=n/klen; for(ll i=1;i<=ksum;i++) { L[i]=R[i-1]+1; R[i]=R[i-1]+klen; } if(R[ksum]<n) { ksum++; L[ksum]=R[ksum-1]+1; R[ksum]=n; } for(ll i=1;i<=ksum;i++) { mul[i]=1; for(ll j=L[i];j<=R[i];j++) { pos[j]=i; } } } ll query(ll l) { return ((a[l]*mul[pos[l]])%p+add[pos[l]])%p; } void update_add(ll l,ll r,ll val) { if(pos[l]==pos[r]) { for(ll i=L[pos[l]];i<=R[pos[l]];i++) { a[i]=query(i); } mul[pos[l]]=1; add[pos[l]]=0; for(ll i=l;i<=r;i++) { a[i]=(a[i]+val)%p; } } else { for(ll i=L[pos[l]];i<=R[pos[l]];i++) { a[i]=query(i); } mul[pos[l]]=1; add[pos[l]]=0; for(ll i=l;i<=R[pos[l]];i++) { a[i]=(a[i]+val)%p; } for(ll i=pos[l]+1;i<=pos[r]-1;i++) { add[i]=(add[i]+val)%p; } for(ll i=L[pos[r]];i<=R[pos[r]];i++) { a[i]=query(i); } mul[pos[r]]=1; add[pos[r]]=0; for(ll i=L[pos[r]];i<=r;i++) { a[i]=(a[i]+val)%p; } } } void update_mul(ll l,ll r,ll val) { if(pos[l]==pos[r]) { for(ll i=L[pos[l]];i<=R[pos[l]];i++) { a[i]=query(i); } mul[pos[l]]=1; add[pos[l]]=0; for(ll i=l;i<=r;i++) { a[i]=(a[i]*val)%p; } } else { for(ll i=L[pos[l]];i<=R[pos[l]];i++) { a[i]=query(i); } mul[pos[l]]=1; add[pos[l]]=0; for(ll i=l;i<=R[pos[l]];i++) { a[i]=(a[i]*val)%p; } for(ll i=pos[l]+1;i<=pos[r]-1;i++) { mul[i]=(mul[i]*val)%p; add[i]=(add[i]*val)%p; } for(ll i=L[pos[r]];i<=R[pos[r]];i++) { a[i]=query(i); } mul[pos[r]]=1; add[pos[r]]=0; for(ll i=L[pos[r]];i<=r;i++) { a[i]=(a[i]*val)%p; } } } int main() { ll n,pd,l,r,val,i; scanf("%lld",&n); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); a[i]%=p; } init(n); for(i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",&pd,&l,&r,&val); if(pd==0) { update_add(l,r,val); } if(pd==1) { update_mul(l,r,val); } if(pd==2) { printf("%lld\n",query(r)); } } return 0; }
luogu P7137 [THUPC2021 初赛] 切切糕
2024年中国传媒大学程序设计大赛(同步赛)D 小红的矩阵构造(一)
-
由于是 \(1 \sim n\) 的排列,对于第 \(i\) 行满足 \(b_{j}>n-a_{i}\) 的 \(b_{j}\) 恰好有 \(a_{i}\) 个,选择这些位置填
1
即可。第 \(i\) 列同理。点击查看代码
int a[1010],b[1010]; int main() { int n,i,j; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } for(i=1;i<=n;i++) { cin>>b[i]; } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { cout<<(b[j]>n-a[i]); } cout<<endl; } return 0; }
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18066610,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。