Average Rank(思维/线段树)
留坑
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=3e5+10;
const int N=1e6+10;
int n,w,k,x;
ll num[maxn],p[maxn],rk[maxn],lz[maxn],pre[maxn];
double sum[maxn];
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>w;
for(int i=0;i<w;i++){ //第i周
cin>>k;
for(int j=0;j<k;j++){ //p是x的分数,lz记录更新时间
cin>>x;
//更新这一分数段的排名
num[p[x]]+=rk[p[x]]*(i-lz[p[x]]);
lz[p[x]]=i; //当前分数段的更新时间更新
++rk[p[x]]; //当前分数段离开一人排名均增加
sum[x]+=num[p[x]]-pre[x];
//更新下一分数段的排名
++p[x]; //下一分数段
num[p[x]]+=rk[p[x]]*(i-lz[p[x]]);
lz[p[x]]=i;
pre[x]=num[p[x]];
}
}
for(int i=1;i<=n;i++){
num[p[i]]+=rk[p[i]]*(w-lz[p[i]]);
lz[p[i]]=w;
sum[i]+=num[p[i]]-pre[i];
}
for(int i=1;i<=n;i++){
printf("%.9lf\n",1.0+sum[i]/w);
}
return 0;
}
Canvas Line(贪心)
1.创建一个结构体记录每块布的左右区间和钉子数量,使用哈希map记录已经放置的钉子的位置
2.初始时遍历每个钉子更新每块布初始钉子的数量。在这里判断如果有布上面有超过了两个钉子那么就输出impossible
3.首先需要考虑每两块布的交界处是否有钉子,如果两块布的钉子数量都小于2且边界没钉子,那么就在这里添加一个钉子。这里还有一个特别重要的易错点,那就是如果某块布已经有了两个钉子,那么它的左右区间都不能再夹钉子
4.最后对遍历每块布判断是否还需要夹钉子,那么对没钉子的位置夹钉子即可,因为l+10<=r且每块布有且仅有两个钉子,完全不需要考虑超时
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;
struct node{
int l,r;
int num;
}a[maxn];
int n,m;
int L[maxn];
unordered_map<int,int> mp;
vector<int> ans;
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].l>>a[i].r;
}
cin>>m;
for(int i=1;i<=m;i++){
cin>>L[i];
mp[L[i]]=1;
}
int flag=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(a[j].l<=L[i] && a[j].r>=L[i]){
a[j].num++;
if(a[j].num>2) flag=1;
}
}
if(flag) break;
}
if(flag){
puts("impossible");
}else{
for(int i=1;i<n;i++){
if(a[i].r==a[i+1].l && a[i].num<2 && a[i+1].num<2 && !mp[a[i].r]){
mp[a[i].r]=1;
//cout<<a[i].r<<endl;
ans.push_back(a[i].r);
a[i].num++;
a[i+1].num++;
}
if(a[i].num==2){
mp[a[i].l]=1;
mp[a[i].r]=1;
}
}
for(int i=1;i<=n;i++){
//cout<<a[i].num<<endl;
for(int j=a[i].num;j<2;j++){
for(int k=a[i].l;k<=a[i].r;k++){
if(!mp[k]){
ans.push_back(k);
mp[k]=1;
break;
}
}
}
}
cout<<ans.size()<<"\n";
for(int i=0;i<ans.size();i++)
cout<<ans[i]<<" ";
}
return 0;
}
E. Expeditious Cubing(浮点数处理)
F. Firetrucks Are Red(并查集+离散化)
1.每个人都有若干个数,两个人只要有一个相同的数那么就有直接的联系,也可以通过另外一个人间接联系起来,问所有人能否通过这些数联系起来
2.首席题目说明了最多有2e5个数,而且这些数有很多重复。考虑逆向思考,将每个数对应人的序号存起来做并查集。因为这些数可能很大,那么使用两个哈希map建立对映射,接着使用set存这些数的编号
3.取出每个数对应人的集合中的第一个,将其他人和第一个人判断是否属于一个集合,做并查集操作即可
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;
struct node{
int u,v,w;
node(int a,int b,int c){
u=a,v=b,w=c;
}
};
int father[maxn];
vector<int> G[maxn];
vector<node> ans;
set<int> s;
int n,m,x,cnt;
unordered_map<int,int> mp1,mp2;
int Find(int x){
return father[x]==x?x:father[x]=Find(father[x]);
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
cnt=1;
for(int i=1;i<=n;i++){
father[i]=i;
cin>>m;
while(m--){
cin>>x;
if(!mp1.count(x)){
mp1[x]=cnt;
mp2[cnt]=x;
cnt++;
}
s.insert(mp1[x]);
G[mp1[x]].push_back(i);
}
}
for(auto it: s){
int ft=G[it][0];
int fx=Find(ft);
for(int i=1;i<G[it].size();i++){
int fy=Find(G[it][i]);
if(fx!=fy){
father[fy]=fx;
ans.push_back(node(ft,G[it][i],mp2[it]));
}
}
}
int res=0;
for(int i=1;i<=n;i++) if(father[i]==i) res++;
if(res==1){
for(auto it: ans){
cout<<it.u<<" "<<it.v<<" "<<it.w<<"\n";
}
}else puts("impossible");
return 0;
}
G. Gnoll Hypothesis(期望/概率)
留坑
I. Inverted Deck(暴力)
直接找出第一段不符合的区间反转,存到另一个数组判断是否符合非降序序列
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=1e6+10;
int n;
int a[maxn],b[maxn];
int check(int *res){
for(int i=1;i<n;i++)
if(res[i+1]<res[i]) return i;
return 0;
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int cur=check(a);
if(!cur){
puts("1 1");
}else{
int l=cur,r=cur;
for(int i=cur;i>=1;i--){
if(a[i-1]==a[i]) l--;
else break;
}
for(int i=cur;i<n;i++){
if(a[i+1]<=a[i]){
r++;
}else break;
}
//cout<<l<<" "<<r<<endl;
memcpy(b,a,sizeof a);
for(int i=l,j=r;i<=r && j>=l;i++,j--)
b[i]=a[j];
//for(int i=1;i<=n;i++) cout<<b[i]<<" ";
if(!check(b)) printf("%d %d\n",l,r);
else puts("impossible");
}
return 0;
}