数位排序 前缀和与差分
若将一维数组a的[l,r]区间加上c 且时间复杂度为O(n)
设b[]是 a[]的差分 先将a的[l,+∞]加上c 再讲a[r+1,+∞]减去c
1 2 3 4
| void insert(int l,int r){ b[l]+=c; b[r+1]-=c; }
|
统计出现的次数cnt[]记录
1 2 3 4 5 6 7 8 9 10 11 12
| while(m--){ int l,r;scanf("%d%d",&l,&r); cnt[l]++;cnt[r+1]--; } for(int i=1;i<=n;i++)cnt[i]+=cnt[i-1]; sort(a+1,a+n+1);sort(cnt+1,cnt+1+n); ll sum2=0; for(int i=1;i<=n;i++)sum2+=cnt[i]*a[i]; printf("%lld",sum2-sum1);
|
孤独的照片
给一个只含’A’,’B’两种字符的字符串
找出所有字串中 含有单个元素的个数
input:
5
GHGHG
output:
3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 易知'A'和'B'地位相同 情况分为两种 ① AAB BAAA B前面或者后面A的个数-1 即为方案数 ② ABA ABAA B前后A的个数之积 即为方案数 先预处理打上序号 const int N=5e5+5; ll g[2][N],h[2][N];
for(int i=1;i<=n;i++){ if(c[i]=='H') h[0][i]=h[0][i-1]+1; else g[0][i]=g[0][i-1]+1; } for(int i=n;i>=1;i--){ if(c[i]=='H') h[1][i]=h[1][i+1]+1; else g[1][i]=g[1][i+1]+1; }
ll ans=0; for(int i=1;i<=n;i++){ if(c[i]=='H'){ if(c[i-1]=='G'&&g[0][i-1]>1) ans+=g[0][i-1]-1; if(c[i+1]=='G'&&g[1][i+1]>1) ans+=g[1][i+1]-1; if(c[i-1]=='G'&&c[i+1]=='G') ans+=g[0][i-1]*g[1][i+1]; } else{ if(c[i-1]=='H'&&h[0][i-1]>1) ans+=h[0][i-1]-1; if(c[i+1]=='H'&&h[1][i+1]>1) ans+=h[1][i+1]-1; if(c[i-1]=='H'&&c[i+1]=='H') ans+=h[0][i-1]*h[i+1]; } }cout<<ans<<endl;
|
统计次数 记忆化递归
求从1到n这n个正整数的十进制表示中 k出现的次数。
1≤ n≤ 10^6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const int N=1e6+5; int f[N],v[N]={1}; int count(int i,int k){ if(v[i]) return f[i]; f[i]=f[i/10]+(i%10)==k; v[i]=1; return f[i]; } int main(){ int n,k;cin>>n>>k; int ans=0; for(int i=1;i<=n;i++){ ans+=count(i,k); } cout<<ans<<endl; }
|
上课睡觉 数论
有 N 堆石子,每堆的石子数量分别为 a1,a2,…,aN。
可以对石子堆进行合并操作,将两个相邻的石子堆合并为一个石子堆,例如,如果 a=[1,2,3,4,5],合并第 2,3 堆石子,则石子堆集合变为 a=[1,5,4,5]。
我们希望通过尽可能少的操作,使得石子堆集合中的每堆石子的数量都相同。
请你输出所需的最少操作次数。本题一定有解,因为可以将所有石子堆合并为一堆。
1≤ N ≤10^5
设操作x次成功 合并后有N-x堆
设每组有y个 y*(N-x)=Σai
性质有 sum%y==0 当y最小时 x也取到最小
可以从小到大枚举sum的因数 并检测一下是否符合题意
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| const int N=1e5+5; int n; int a[N]; bool check(int y){ int t=0; for(int i=1;i<=n;i++){ t+=a[i]; if(t==y)t=0; else if(t>y)return false; } return true; } void volve(){ int mx=0,sum=0; cin>>n;for(int i=1;i<=n;i++){ cin>>a[i];sum+=a[i];mx=max(a[i],mx); } if(mx==0){ cout<<"0"<<endl; return; } for(int i=mx;i<=sum;i++){ if(sum%i==0&&check(i)){ cout<<n-sum/i<<endl; return; } }
} int main(){ int t;cin>>t; while(t--)solve(); return 0; }
|