A
按題意直接模擬即可。也就是每次取出一些字元,放入字串\(P\)中。
注意實現時的時間複雜度,不要寫成 \(O(n^2)\) 的。
#include<bits/stdc++.h>
using namespace std;
char s[1000010],t[1000010];
int hd1=1,hd2=1,n,m,x,y;
char ans[2000010];
int main()
{
scanf("%s",s+1);n=strlen(s+1);
scanf("%s",t+1);m=strlen(t+1);
scanf("%d%d",&x,&y);
while(hd1<=n||hd2<=m)
{
for(int i=1;hd1<=n&&i<=x;i++)
putchar(s[hd1++]);
for(int i=1;hd2<=m&&i<=y;i++)
putchar(t[hd2++]);
}
}
B
發現一定是小羊優先匹配小牛,小牛匹配小羊,並且今日準備餅乾數量多的店主優先匹配,最後可能還會剩下一些無法匹配的店主。
可以先分類再排序,然後貪心選擇就可以取到最大值。
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct item
{
int tp,val;
};
item a[100010];
long long ans=0;
bool cmp(item x,item y)
{
if(x.tp!=y.tp)
return x.tp<y.tp;
return x.val>y.val;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].tp,&a[i].val);
sort(a+1,a+n+1,cmp);
int c0=m,c1=n-m;
for(int i=1;i<=n;i++)
{
if(a[i].tp==1)
{
if(c0>0)
c0--,ans+=a[i].val*2;
else
c1--,ans+=a[i].val;
}
else
{
if(c1>0)
c1--,ans+=a[i].val*1.5;
else
c0--,ans+=a[i].val;
}
}
printf("%lld\n",ans);
}
C
考慮 \(C_{i,j}\) 和 \(C_{i,j+1}\) 的差為 \(|A_i+B_j-A_i-B_{j+1}|\) ,也就是 \(|B_j-B_{j+1}|\) ,\(C_{i+1,j}\) 同理。
由此可發現,走回頭路一定不優,且所有隻向右和向下的方案代價都一樣,所以答案就是 \(\sum_{i=1}^{n-1}|A_i-A_{i+1}|+\sum_{i=1}^{m-1}|B_i-B_{i+1}|\)
#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[1000010], b[1000010];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) scanf("%d", &b[i]);
long long sum = 0;
for (int i = 2; i <= n; i++) sum += abs(a[i] - a[i - 1]);
for (int i = 2; i <= m; i++) sum += abs(b[i] - b[i - 1]);
printf("%lld\n", sum);
}
D
考慮記錄每個士兵是否得到了軍令。
將所有時間按照時間順序排序後,按時間順序模擬所有事件的發生即可,即如果兩個士兵中有一個得到了訊息,則記錄下另一個士兵得到訊息的資訊。
#include<bits/stdc++.h>
using namespace std;
int n,m;
int t;
bool vis[1000010];
struct event
{
int x,y;
double ti;
};
bool cmp(event x,event y)
{
return x.ti<y.ti;
}
event p[500010];
int cnt=0;
int a[100010],b[100010];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
vis[i]=0;
cnt=0;
vis[m]=1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
if(a[i]==a[j])
p[++cnt]=(event){i,j,0};
else if(b[i]!=b[j]&&(a[i]>a[j])!=(b[i]>b[j]))
p[++cnt]=(event){i,j,1.0*(a[i]-a[j])/(b[j]-b[i])};
}
sort(p+1,p+cnt+1,cmp);
for(int i=1;i<=cnt;i++)
vis[p[i].x]|=vis[p[i].y]|=vis[p[i].x];
int ans=0;
for(int i=1;i<=n;i++)
ans+=vis[i];
printf("%d\n",ans);
}
}
E
考慮每一位的貢獻是獨立的, 那麼可以分別對每一位做。
從左到右掃一遍, 對每一位維護兩個值, 分別表示當前總共有多少個 \(1\) , 當前異或起來總共有多少個 \(1\) , 即維護了 \(a_i\) 以及 \(a_i \oplus a_j\) 。
可能稍微有點卡常, 可以參考 std。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
int n, k;
ull a[4000005], ans, U, seed;
int main() {
scanf("%d%llu%d", &n, &seed, &k);
srand(seed);
U = (k == 64 ? 0ull : (1ull << k)) - 1ull;
mt19937_64 rnd(seed);
for(int i = 1; i <= n; i++) a[i] = rnd() & U;
ull ans = 0;
for(int i = 0; i < k; i++) {
ull cnt0 = 0, cnt1 = 0, t = 0, res = 0;
for(int j = 1; j <= n; j++) {
bool fl = (a[j] >> i) & 1;
res += fl * 1ull * (j - 2) * (j - 1) / 2 + (!fl) * t, cnt1 += fl, cnt0 += !fl, t += fl * cnt0 + (!fl) * cnt1;
}
ans += res * (1ull << i);
}
printf("%llu\n", ans);
return 0;
}