A
题意:有两座高分别为n,m的塔,塔是由多个高为1的红/蓝方块搭成。告诉你两座塔的颜色组成,问能否可以经过若干次操作使两座塔都没有相邻块颜色相同。每次操作,可以把其中一座塔顶移到另一座塔上。
思路:我们可以把A串和B串反向连接起来,只要相邻方块颜色相同的次数不超过1,就是YES,否则No。
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
string A,B;
int n,m;
void solve()
{
cin>>n>>m;
cin>>A>>B;
reverse(A.begin(),A.end());
B+=A;
int cnt=0;
for(int i=0;i<B.length()-1;i++)
{
if(B[i]==B[i+1]) cnt++;
}
if(cnt<=1) puts("YES");
else puts("NO");
}
signed main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
// ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
B
题意:给定n条线段(从l到r),定义f(x)为覆盖点x的区间个数。给定k,问能否通过删除若干区间的方式,使k满足对于任意x,f(k)>f(x)。
思路:差分统计覆盖次数,把f(x)>=f(k)的点存起来。若要是删除区间,则一定是删除覆盖x,不覆盖k的区间。我们对于每个x,统计这样的区间个数,比较区间个数与f(x)-f(k)的大小关系。若所有点的区间个数都大于f(x)-f(k),则yes
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n,k;
int d[N];
int sum[N];
struct node{
int l,r;
}a[N];
void solve()
{
for(int i=0;i<=50;i++) d[i]=0;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
int l,r;
cin>>l>>r;
a[i]={l,r};
d[l]++,d[r+1]--;
}
for(int i=1;i<=50;i++)
sum[i]=sum[i-1]+d[i];
queue<PII>q;
for(int i=1;i<=50;i++)
{
if(sum[i]>=sum[k]&&i!=k) q.push({sum[i],i});
}
bool f=1;
while(q.size())
{
int t=q.front().second,num=sum[t]-sum[k];
q.pop();
bool has=0;
for(int i=1;i<=n;i++)
{
if(a[i].l<=t&&a[i].r>=t&&(a[i].l>k||a[i].r<k))
{
num--;
}
}
if(num>=0)
{
f=0;
break;
}
}
if(f) puts("YES");
else puts("NO");
}
signed main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
C
题意:有n杯茶,每杯茶的体积是ai,有n个人品茶,每个人喝一口的体积是bi。品茶有n轮,第一轮,i号人品i号茶;第二轮,i号人品i-1号茶,1号人不品。问品茶结束后,每个人喝了多少。
思路:设对于第i杯茶,它可以完全满足[i,j]号人喝茶需求,对于个j,我们可以利用前缀和与二分求出(对b求前缀和,求sum[j]-sum[i-1]<=a[i])。那么i~j号都可以喝上完整一口(差分),剩余的茶被j+1号人喝。
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
#define int long long
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
int a[N];
int b[N];
int sumb[N];
int d[N];
int ans[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) ans[i]=0,d[i]=0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++) sumb[i]=sumb[i-1]+b[i];
for(int i=1;i<=n;i++)
{
int l=0,r=n;
while(l<r)
{
int mid=l+r+1>>1;
if(sumb[mid]-sumb[i-1]>a[i]) r=mid-1;
else l=mid;
}
d[i]++;d[l+1]--;
if(l+1<=n) ans[l+1]+=a[i]-(sumb[l]-sumb[i-1]);
}
for(int i=1;i<=n;i++) d[i]=d[i-1]+d[i];
for(int i=1;i<=n;i++)
ans[i]+=d[i]*b[i];
for(int i=1;i<=n;i++)
cout<<ans[i]<<" \n"[i==n];
}
signed main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
D
题意:给定n个点,点1,2,3、4,5,6...每三个点组成一个三元组。三元组内形成一个三角形。三元组间没有边相连。现在你需要对这些点进行涂色,涂成红或蓝色,且红色、蓝色点个数都为n/2。涂色方案的价值定义为:连接不同色顶点的边的权重之和。求最大涂色价值的方案数。
思路:因为最大涂色价值,所以涂色方法是最小权重边两端颜色同,另外的点涂另一种颜色。问题转化成在m个三角形中,选择m/2个三角形涂成一红二蓝,另一半m/2个三角形涂成一蓝二红。涂色方案数为C(m,m/2)
在三角形内部,边权情况如下:
4 4 4三边权重相同,三种
4 4 2两个长边相同,一种
2 2 4两个短边相同,两种
2 3 4三边不同,一种
求组合数可以用Lucas定理。
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0), cin.tie(0)
#define PII pair<int, int>
#define int long long
typedef long long ll;
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod=998244353;
using namespace std;
int n;
int a[N];
int qmi(int a,int k)
{
int ret=1%mod;
while(k)
{
if(k&1) ret=(ll)ret*a%mod;
k>>=1;
a=(ll)a*a%mod;
}
return ret;
}
int C(int a, int b)
{
if(a<b) return 0;
int ret = 1;
for (int i = 1, j = a; i <= b; i++, j--)
{
ret = (ll)ret * j % mod;
ret = (ll)ret * qmi(i, mod - 2) % mod;
}
return ret;
}
int lucas(ll a, ll b)
{
if (a < mod && b < mod)
return C(a, b);
return (ll)C(a % mod, b % mod) * lucas(a / mod, b / mod) % mod;
}
void solve()
{
cin >> n;
int ret = lucas(n/3,n/6);
for (int i = 1; i <= n; i++) cin >> a[i];
int t=1;
for(int i=1;i<=n;i+=3)
{
sort(a+i,a+i+2+1);
if(a[i+2]==a[i+1])
{
if(a[i+1]!=a[i])//2 4 4
{
t*=1;
}
else //4 4 4
{
t=t%mod*3%mod;
}
}
else
{
if(a[i+1]!=a[i]) //2 3 4
{
t*=1;
}
else //2 2 4
{
t=t%mod*2%mod;
}
}
}
cout<<ret%mod*t%mod<<'\n';
}
signed main()
{
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
// ios;
int _t = 1;
// cin>>_t;
while (_t--)
solve();
system("pause");
return 0;
}