iwtgm-34

发布时间 2023-12-12 18:34:53作者: WW爆米花

Educational Codeforces Round 159 (Rated for Div. 2)

A.

只要有0就是yes
因为若只有0,显然满足条件
若0和1都有,一定会有01相邻的情况,我们插入0后,仍有01相邻的情况,即我们可以无限+0,那么最后0的个数一定可以大于1

void solve() {
    int n;cin>>n;
    string s;cin>>s;
    int cnt_0=0,cnt_1=0;
    for(int i=0;i<s.size();i++){
        if(s[i]=='0')cnt_0++;
        else cnt_1++;
    }
    if(cnt_0&&cnt_1||cnt_0){
        cout<<"YES"<<endl;
    }
    else cout<<"NO"<<endl;
}

B.

这种题思路容易出,但代码实现还是有点东西

#define int long long
void solve() {
    int n, P, l, t;
    cin >> n >> P >> l >> t;
    int x = (n + 6) / 7;
    // debug1(x);
    int s = (x / 2) * (l + t * 2);
    int ss = s + (x % 2) * (l + t);
    int d = (l + t * 2);
    if(s >= P){
        cout << n - (P + d - 1) / d << endl;
    }
    else if(ss >= P){
        cout << n - (x + 1) / 2 << endl;
    }
    else {
        P -= ss;
        int ans = (x + 1) / 2 + (P + l - 1) / l;
        cout << n - ans << endl;
    }
}

C.

想错的点是a(n+1)可以比a(n)小

#define int long long
 
 
void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    set<int> st;
    for(auto &i : a) {
        cin >> i;
        st.insert(i);
    }
    vector<int> ans;
    sort(a.begin(), a.end());
    int mx = a.back();
    for(auto i : a) {
        if(mx - i != 0)
            ans.push_back(mx - i);
    }
    if(!ans.size()) {
        cout << 1 << endl;
        return ;
    }
    int gc = ans[0];
    for(int i = 1; i < ans.size(); i++) {
        gc = __gcd(gc, ans[i]);
    }
    int res = 0;
    for(int i = 1; i <= n; i++) {
        if(!st.count(mx - gc * i)) {
            res = i;
            break;
        }
    }
    if(res == 0)res = n;
    for(auto i : ans) {
        res += i / gc;
    }
    cout << res << endl;
}

D.

思路一直绕在点中心转换,其实不用
就按它题意,算偏移量,然后去二分查找是否存在

#define x first
#define y second
#define pt pair<int,int>
 
void solve() {
    int n,q;cin>>n>>q;
    string s;cin>>s;
    vector<pt>pos(n+1);
    for(int i=0;i<n;i++){
        pos[i+1].x=pos[i].x+(s[i]=='R')-(s[i]=='L');
        pos[i+1].y=pos[i].y+(s[i]=='U')-(s[i]=='D');
    }
    map<pt,vector<int>>mp;
    for(int i=0;i<=n;i++)mp[pos[i]].push_back(i);
    auto check=[&](pt p,int l,int r){
        if(!mp.count(p))return false;
        auto it= lower_bound(mp[p].begin(),mp[p].end(),l);
        return it!=mp[p].end()&&*it<=r;
    };
    while(q--){
        int x,y,l,r;cin>>x>>y>>l>>r;
        int nx=pos[r].x+pos[l-1].x-x,ny=pos[r].y+pos[l-1].y-y;
        bool f=check({x,y},0,l-1)|check({nx,ny},l,r-1)|check({x,y},r,n);
        cout<<(f?"YES":"NO")<<endl;
    }
}

E.

用字典树就可以很好地解决了

using ll = long long;
using pii = pair<int, int>;
using vint = vector<int>;
using vpo = vector<pii>;
 
vector<string> s(1000006);
int trie[1000006][26],cnt[1000006][26], tot = 0;
void insert(string str) {
    int p = 0;
    for (auto& c : str) {
        int ch = c - 'a';
        if (trie[p][ch] == 0)trie[p][ch] = ++tot;
        ++cnt[p][ch];
        p = trie[p][ch];
    }
}
ll que(string str) {
    int p = 0; ll ret = 0;
    for (int i = str.size() - 1; i >= 0; i--) {
        int ch = str[i] - 'a';
        ret += cnt[p][ch];
        p = trie[p][ch];
        if (p == 0)break;
    }
    ll size = str.size();
    return ret;
}
int main(void)
{
    IOS;
    int n; cin >> n;
    ll sumlen = 0;
    for (int i = 1; i <= n; i++) {
        cin >> s[i];
        insert(s[i]);
        sumlen += s[i].size();
    }
    ll ans=sumlen* 2 * n;
    for (int i = 1; i <= n; i++) {
        ans -= que(s[i])*2;
    }
    cout << ans << endl;
}

F.
浅学下异或线性基
异或性质:
若a\(\bigoplus\)b\(\bigoplus\)c=0,则a\(\bigoplus\)b=c
若a\(\bigoplus\)b=c,则a\(\bigoplus\)c=b

异或线性基:若集合a中的每一个数都能用集合b中的若干个(可为0个)数按位异或得出,
且集合b是满足上述要求的元素个数最少的集合,那么称b是a的一个异或线性基

a[]储存所有的线性基
a[i]表示线性基中(先出现的)最高位为i的元素(唯一,就是说这一位为1就标志着这个数,其他数都被抵消)(后面的这一位会被抵消,后面会再说)
如果a[i]=0,表示线性基里还没有最高位为第i位的元素
将元素x插入线性基里,从高到低枚举x的每一个二进制位
假设枚举到第i位
如果a[i]=0,那就说明x的第i位不能被目前线性基里的数异或出,所以必须把x插入线性基,即a[i]=x;
否则,我们要把x的第i位用a[i]消掉,也就是x^a[i].(这就是为什么我们要让线性基内任意两个数的二进制最高位不同,因为这样才能起到消位的作用)

#define int long long
int n;
int a[51];
void get_lb(int x){
    for(int i=50;i>=0;i--){
        if((x&(1ll<<i))==0)continue;
        if(a[i]>0)x^=a[i];
        else{
            a[i]=x;
            return ;
        }
    }
}
void solve() {
    cin>>n;
    for(int i=1;i<=n;i++){
        int k;cin>>k;
        get_lb(k);
    }
}