Gym 102215 & 队内训练#5

A - Rooms and Passages

题意:找到每个数后面第一个负正对。

从前往后比较麻烦。从后向前,先记录正数位置,一旦出现这个数的相反数即产生一对负正对,通过和前面的负正对比较更新答案。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int maxn = 5e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll Map[maxn];
ll ans[maxn];
ll a[maxn];

int main()
{
    ll n = read();
    rep(i,1,n) a[i] = read();
    int pre = inf;
    per(i,n,1)
    {
        if(a[i]>0)
        {
            if(pre==inf)  Map[a[i]] = i,ans[i] = n-i+1;
            else
            {
                ans[i] = pre - i;
                Map[a[i]] = i;
            }
        }
        else
        {
            if(!Map[-a[i]])
            {
                ans[i] = min(pre - i,n - i + 1);
            }
            else
            {
                ans[i] = min(Map[-a[i]] - i,pre-i);
                pre = min(pre,Map[-a[i]]);
            }
        }
    }
    rep(i,1,n) cout<<ans[i]<<' ';cout<<endl;
    return 0;
}

B - Rearrange Columns

题意:给你一个(2*n)矩阵,只含有#和. , 问你在可以交换任意列的情况下能否使得#联通。

思路:列只有四种情况
1 #和.
2 .和#
3 #和#
4 .和.
只有在3不存在且12同时存在的时候才会NO。
其他情况下就3放中间其他放两边即可。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;

const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

vector<ll> fi_type;
vector<ll> se_type;
vector<ll> th_type;
vector<ll> es_type;

int main()
{
    char s[3][5000];
    char ans[3][5000];
    gets(s[1]+1);
    gets(s[2]+1);
    int len = strlen(s[1]+1);
    rep(j,1,len)
    {
        if(s[1][j]=='#'&&s[2][j]=='#') fi_type.pb(j);
        else if(s[1][j]=='#'&&s[2][j]=='.') se_type.pb(j);
        else if(s[1][j]=='.'&&s[2][j]=='#') th_type.pb(j);
        else es_type.pb(j);
    }
    if(fi_type.size()==0&&se_type.size()&&th_type.size())
    {
        cout<<"NO"<<endl;
    }
    else
    {
        cout<<"YES"<<endl;
        per(j,len,1)
        {
            if(th_type.size())
            {
                int cur = th_type[th_type.size()-1];
                ans[1][j] = s[1][cur], ans[2][j] = s[2][cur];
                th_type.pop_back();
            }
            else if(fi_type.size())
            {
                int cur = fi_type[fi_type.size()-1];
                ans[1][j] = s[1][cur], ans[2][j] = s[2][cur];
                fi_type.pop_back();
            }
            else if(se_type.size())
            {
                int cur = se_type[se_type.size()-1];
                ans[1][j] = s[1][cur], ans[2][j] = s[2][cur];
                se_type.pop_back();
            }
            else
            {
                int cur = es_type[es_type.size()-1];
                ans[1][j] = s[1][cur], ans[2][j] = s[2][cur];
                es_type.pop_back();
            }

        }
        rep(i,1,2) rep(j,1,len)
        {
            cout<<ans[i][j];
            if(j==len) cout<<endl;
        }
    }
    return 0;
}


C - Jumps on a Circle

题意:给你一个大小为p,编号从(0~p-1)的环,从0开始往前跳,步长从1开始每次增1,问跳了n次后有多少个格子被踩到过。

思路:当前的位置即是
pos = ({{n(n-1)}over 2}) (\%p)
当n = 2p时 pos = 0,
当n = 2p+1时, pos = (p(p-1)+2p + 1)%p = 1。
即发现2p为一个循环节。所以总的遍历次数不超过2p,O(2p)遍历一遍就可以了。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e7+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll vis[maxn];

int main()
{
    ll p = read(), n = read();
    n = min(n,2*p+1);
    ll cur = 0;
    vis[0] = 1;
    ll step = 1;
    ll ans = 1;
    while(n--)
    {
        cur += step;
        cur %= p;
        if(!vis[cur]) ans ++;
        vis[cur] = 1;
        step ++;
    }
    cout<<ans<<endl;
    return 0;
}


J - The Power of the Dark Side - 2

题意:有n个人,每个人有三个属性,如果这个人有两个属性比其他某个人的这两个属性都高,就能打败他。现在可以在攻击的时候调整自身属性,重新分配技能点,问每个人最多能打败多少人。

思路:贪心。肯定是先分配一个0打对方的最高的,自己剩下来的平分给自己两个属性来打对面。所以只用看自己的三者和-2(至少比对方最小两个都大1)能否大于等于对方的两个最小的和,外层遍历n个人,内层二分即可。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int maxn = 5e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

typedef struct Information
{
    ll sum2;
    ll sum3;
    ll id;
    Information(){}
    Information(ll a, ll b): sum2(a), sum3(b){}
    bool operator< (const Information& a)
    {
        if(sum2!=a.sum2)
        return sum2 < a.sum2;
        return sum3 < a.sum3;
    }
}I;
I a[maxn];
ll Ans[maxn];
ll Map[maxn];

int main()
{
    ll n = read();
    rep(i,1,n)
    {
        ll b[5];
        b[1] = read(), b[2] = read(), b[3] = read();
        sort(b+1,b+1+3);
        a[i].sum2 = b[1] + b[2];
        a[i].sum3 = b[1] + b[2] + b[3];
        a[i].id = i;
    }
    sort(a+1,a+1+n);
    ll ans = 0;
    a[n+1].sum2 = 1e15;
    rep(i,1,n)
    {
        int idx = lower_bound(a+1,a+1+n,Information(a[i].sum3-2,1e15)) - a;
        if(idx==i) idx--;
        else if(a[idx].sum2==a[i].sum3-2) ;
        else
        {
            if(a[i].sum2>=a[idx].sum2)
            idx --;
            else idx -= 2;
        }
        Ans[a[i].id] = idx;
    }
    rep(i,1,n) cout<<Ans[i]<<' ';
    cout<<endl;
    //cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/Bgwithcode/p/13948015.html