A. Chess Placing

思路:一半奇数位,一半偶数位。一一对应即可,注意别忘记排序

B. Switches and Lamps

思路:暴力模拟O(n*m)

C. Liebig's Barrels【贪心】

思路:sort后,求出最右边的木板最大的区间范围[1,r]。尽量让h小的放在一起,假设r个里面能造t个木桶。那么有不等式   r-k*t<=n-t ,求出最大的t。然后[kt+1,r]不能再构成桶了,于是取kt+1,从r往前取n-t-1个板。

D. Sand Fortress【贪心+二分】

思路:手动模拟。发现堆数x越大,能堆的城堡范围在[k,max]越大。只要n在[1,max]的范围内,则必定存在一个x'<=x使得其满足n堆的沙丘.

#pragma comment(linker, "/stack:100000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
#define debug puts
#define setp cout << fixed << setprecision(15)
#define fst ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+5;
typedef long long ll;
ll n,h;
ll cul(ll x){
    return x*(x+1)/2;
}
bool check(ll k){
    if(k<=h){
        if( (1+k)*k/2 >= n) return true;
        else    return false;
    }
    ll sum=0;
    if(h%2==0){
        ll best=k-h;
        ll most=h+best/2;
        if(k%2==1)  sum=2*cul(most)-cul(h-1);
        else    sum=cul(most)+cul(most-1)-cul(h-1);
    }
    else{
        ll best=k-h;
        ll most=h+best/2;
        if(k%2==0)  sum=2*cul(most)-cul(h-1);
        else    sum=cul(most)+cul(most-1)-cul(h-1);
    }
//    cout <<"sum="<<sum<<endl;
//    cout << sum-n << endl;
    if(sum>=n)  return true;
    else return false;
}

int main(void){
    fst;
    cin >> n >> h;
    ll l=1,r=2e9,ans;
//    cout <<check(7) << endl;;
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(mid))  /*cout <<"~"<<mid<<endl,*/ans=mid,r=mid-1;
        else    l=mid+1;
    }
    cout << ans << endl;

    return 0;
}

E. Pencils and Boxes(DP)

思路:把当前区间划分成若干个区间

条件1:每个区间max-min<=d

条件2:区间大小不小于k个

dp[i]:前i个物品是否能按要求划分,能是1,否则为0;

根据条件1,可以判断下届L,根据>=k可以判断出上届R.那么只要当dp[L~R]有一个成立,那么dp[i]就一定可以成立,用树状数组logn维护.这题问区间是否能划分,重点考虑DP

#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
#define debug puts
#define setp cout << fixed << setprecision(15)
#define fst ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=5e5+5;
typedef long long ll;
ll a[N];
int t[N];
ll n,k,d;
void update(ll x){
    for(ll i=x;i<=n;i+=i&(-i))  t[i]+=1;
}

ll query(ll x){
    ll ans=0;
    for(ll i=x;i;i-=i&(-i)) ans+=t[i];
    return ans;
}

int main(void){
    fst;
    cin >>n >> k>>d;
    for(ll i=1;i<=n;i++)   cin >> a[i];
    sort(a+1,a+1+n);
    for(ll i=k;i<=n;i++){
        ll l=lower_bound(a+1,a+1+n,a[i]-d)-a;
        l--;
        if(l==0)    l=1;
        ll r=i-k;
        if(a[i]-a[1]<=d){
            update(i);
            continue;
        }
        if(r<l) continue;
        ll sum=query(r)-query(l-1);
        if(sum>0)   update(i);
    }
    if(query(n)-query(n-1)>0)    cout <<"YES"<<endl;
    else    cout <<"NO"<<endl;

    return 0;
}

F. Isomorphic Strings(哈希)

思路:两个串s1,s2的每一个位置存在一一映射的关系.那么把s1串的字母'A'出现的位置用一个数字来代表,'B'同理. 对于串s2,也同理. 那么sort看看是不是2个串所有字母的代表数字相同

#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
#define debug puts
#define setp cout << fixed << setprecision(15)
#define fst ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+5;
typedef long long ll;
char s[N];
int n,q;

struct Hash{
    ll Seed,Mod;
    ll sum[26][N],bas[N];
    void init(){
        bas[0]=1;
        for(int i=1;i<=n;i++)  bas[i]=bas[i-1]*Seed%Mod;

        for(int i=0;i<26;i++){
            for(int j=1;j<=n;j++){
                sum[i][j]=( sum[i][j-1]*Seed%Mod+ (s[j]-'a'==i?1:0) )%Mod;
            }
        }
    }
    ll gethash(ll *t,int l,int r){
        return (((t[r]-t[l-1]*bas[r-l+1]%Mod)+Mod)%Mod);
    }
}gen[2];

void solve(){
    int x,y,len;
    scanf("%d%d%d",&x,&y,&len);
    ll a[2][30],b[2][30];
    for(int i=0;i<=1;i++){
        for(int j=0;j<26;j++){
            a[i][j]=gen[i].gethash(gen[i].sum[j],x,x+len-1);
            b[i][j]=gen[i].gethash(gen[i].sum[j],y,y+len-1);
        }
    }
    for(int i=0;i<=1;i++)
        sort(a[i],a[i]+26),sort(b[i],b[i]+26);
//    for(int i=0;i<26;i++){
////        printf("%d -> %I64d %I64d\n",i,a[1][i],b[1][i]);
//    }
//    for(int i=0;i<=1;i++){
        for(int j=0;j<26;j++){
            if(a[0][j]!=b[0][j] || a[1][j]!=b[1][j]){
                printf("NO\n");
                return ;
            }
        }
//    }
    printf("YES\n");
    return ;
}

void hash_init(){
    gen[0].Seed=146527,gen[0].Mod=1e9+9;
    gen[1].Seed=19260817,gen[1].Mod=998244353;
    for(int i=0;i<=1;i++){
        gen[i].init();
    }
}

int main(void){
//    fst;
    scanf("%d%d",&n,&q);
    scanf("%s",s+1);
    hash_init();
    while(q--){
        solve();
    }

    return 0;
}