[广告位招租]
Update:I题已补
A - Acowdemia I
题意
Bessie写了 N N N篇论文,第 i i i篇论文被引用了 c i c_i ci次
h h h-index表示一个最大的值 h h h,使得至少有 h h h篇论文被引用的次数多于 h h h次
现在Bessie想写一篇新论文,用来刷旧论文的引用次数
每篇旧论文最多被引用一次,并且这篇新论文中最多引用 L L L篇旧论文
问在写完这篇新论文后, h h h-index的最大值是多少
Bessie的做法可能会引发学术诚信问题,建议大家不要学习
标签
Implementation
Prefix-Sum
思路
因为只能写一篇新论文,并且每篇旧论文最多被引用一次
引用次数的数据范围只有 1 0 5 10^5 105,所以可以先记录下每种引用次数的论文有多少篇( c n t [ i ] cnt[i] cnt[i]表示引用次数为 i i i的论文篇数)
直接枚举 h h h作为引用次数的下限,那么可以根据前缀和直接取得原先引用次数 ≥ h \ge h ≥h的篇数 x x x
再贪心让新论文全部引用在引用次数为 h − 1 h-1 h−1的旧论文上,使其尽可能增加一次引用次数,涉及到的论文篇数为 y = m i n ( L , c n t [ h − 1 ] ) y=min(L,cnt[h-1]) y=min(L,cnt[h−1])
最后判断 x + y ≥ h x+y\ge h x+y≥h是否成立即可
代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
int n,l;
int a[100050],b[100050],s[100050];
void solve()
{
cin>>n>>l;
rep(i,1,n)
{
cin>>a[i];
b[a[i]]++;
}
s[0]=b[0];
rep(i,1,100000)
s[i]=s[i-1]+b[i];
int r=0;
rep(i,1,n)
{
int t=n-s[i-1];
//cout<<i<<' '<<t<<'\n';
t+=min(b[i-1],l);
if(t>=i)
r=i;
}
cout<<r<<'\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
B - Acowdemia III
题意
一张 n × m n\times m n×m的图,每个点可能有一头牛、一堆草,或者什么也没有
如果某一堆草与某两头牛都相邻,那么这两头牛就可以走一步来到这堆草所在的位置,并且两头牛可以成为朋友
一旦两头牛在某一堆草的位置成为了朋友,那么其他牛便不能再到这堆草的位置来
一头牛可以与多头其他牛成为朋友,假设每次与其他牛成为朋友后,他们都会再回到原来的位置
问最多可以让多少对牛成为朋友
标签
Implementation
思路
考虑每堆草是否能够让某两头牛成为朋友
如果与某堆草相邻的牛只有一头,明显无贡献
如果与某堆草相邻的牛大于等于三头,那么一定可以使得其中两头在这里成为朋友
如果与某堆草相邻的牛有两头,那么需要分情况讨论,特殊的有以下这两种:
C G G C CG\\ GC CGGC
G C C G GC\\ CG GCCG
如果出现上述两种情况,判断与另外对角线上的一堆草相邻的牛的数量是否也为 2 2 2
如果不为 2 2 2,可以让另外一堆草分配给任意其他对牛(只要不同时是图中这两只牛就行),当前枚举到的这堆草贡献 + 1 +1 +1
否则会产生冲突,这两头牛可能可以同时吃这两堆草,但朋友的对数只能 + 1 +1 +1
(对于代码部分)根据枚举顺序,实际上只需要考虑两种方向就行,对于这两种冲突情况,让枚举顺序中后出现的情况不计入答案即可
(口糊极其严重建议直接看代码)
代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const int dx[4]={
0,1,0,-1},dy[4]={
1,0,-1,0};
int n,m;
char mp[1010][1010];
int adjcow[1010][1010];
void solve()
{
cin>>n>>m;
rep(i,1,n)
cin>>mp[i]+1;
rep(i,1,n)
rep(j,1,m)
repp(t,0,4)
adjcow[i][j]+=(mp[i+dx[t]][j+dy[t]]=='C'); //相邻的牛的数量
int ans=0;
rep(i,1,n)
rep(j,1,m)
if(mp[i][j]=='G')
{
if(adjcow[i][j]>2)
ans++;//,cout<<i<<' '<<j<<'\n';
else if(adjcow[i][j]==2)
{
if(mp[i-1][j]=='C'&&mp[i][j-1]=='C'&&mp[i-1][j-1]=='G'&&adjcow[i-1][j-1]==2||
mp[i][j+1]=='C'&&mp[i-1][j]=='C'&&mp[i-1][j+1]=='G'&&adjcow[i-1][j+1]==2) //说明已经在另外一堆草中已经计算过这两头牛的贡献(根据枚举顺序)
continue;
ans++;//cout<<i<<' '<<j<<'\n';
}
}
cout<<ans<<'\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
C - United Cows of Farmer John II
防AK 😦
题意
K题的Hard版本
定义一个三元组 ( i , j , k ) , 1 ≤ i ≤ j ≤ k ≤ n (i,j,k),\ 1\le i\le j\le k\le n (i,j,k), 1≤i≤j≤k≤n是合法的,当且仅当 i , j , k i,j,k i,j,k这三个位置所表示的数在区间 [ i , k ] [i,k] [i,k]中都仅出现一次
问合法的三元组数量
D - Permutation
防AK 😦
题意
给定二维平面中的 N N N个点,可以随意选择这 N N N个点的任意一个排列 p 1 , p 2 , ⋯ , p N p_1,p_2,\cdots,p_N p1,p2,⋯,pN
将 p 1 , p 2 , p 3 p_1,p_2,p_3 p1,p2,p3三个点两两连边
从 i = 4 i=4 i=4开始,每个点尝试与所有 j ( j < i ) j\ (j\lt i) j (j<i)连边,要保证连的边与其他已经连的边不交叉,并且最终整张图中每个点都严格只有三条边
如果存在一个合法的连边方案能够满足上述条件,则这个排列是可行的
问存在多少种可行的排列
E - Acowdemia IV
题意
A题的Hard版本
Bessie写了 N N N篇论文,第 i i i篇论文被引用了 c i c_i ci次
h h h-index表示一个最大的值 h h h,使得至少有 h h h篇论文被引用的次数多于