ICPC North Western European Regional Contest 2019 [待补]

Average Rank(思维/线段树)

传送门

留坑

reference

#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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值