2019nc#7

题号标题已通过代码题解/讨论通过率团队的状态
A String 点击查看 进入讨论 566/3539  通过
B Irreducible Polynomial 点击查看 规律 730/2290 未通过
C Governing sand 点击查看 进入讨论 388/2088  通过
D Number 点击查看 进入讨论 959/1469  通过
E Find the median 点击查看 离散化 88/985 OK
F Energy stones 点击查看 BIT 16/132 未通过
G Make Shan Happy 点击查看 进入讨论 3/29 未通过
H Pair 点击查看 数位DP 93/245 OK
I Chessboard 点击查看 进入讨论 17/83 未通过
J A+B problem 点击查看 进入讨论 1024/1844  通过
K Function 点击查看 进入讨论 8/49 未通过

E-Find the median

题意

n次操作,($n le 400000$),每次给出$L_i, R_i$向集合中插入,让你把$[L_i, L_i+1, L_i+2, ... , R_i]$ 插入到集合中,同时输出集合的中位数。

集合一开始为空,($1 le L_i, R[i] le 1e9$)

思路

空间有限,所以不可以把两个端点间的一段单独拿出来当成一个点

动态开点也被卡了空间

具体思路还是离散化,我们可以中间的点和左端点看成一个点

把原来对闭区间的操作改为对左闭右开区间的操作

就是把原来的$[L_i, R_i]$ 更改为 $[L_i, R_i + 1)$

// #pragma GCC optimize(2)
//  #pragma GCC optimize(3)
//  #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
            const int big = 1e9;
            const int maxn = 400005;
            int X[maxn],Y[maxn];
            int L[maxn], R[maxn];
            int a1,b1,c1,m1;
            int a2,b2,c2,m2;
            struct node{
                int cnt;
                ll sum;
                int lazy;
                int len;
            } tree[maxn * 8];
            //离散化
            vector<int>vec;
            int getid(int x) {
                return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1;
            }
            //

            void pushdown(int le,int ri,int rt) {
                tree[rt<<1].cnt += tree[rt].lazy;
                tree[rt<<1|1].cnt += tree[rt].lazy;
                tree[rt<<1].lazy += tree[rt].lazy;
                tree[rt<<1|1].lazy += tree[rt].lazy;
                int mid = (le + ri) >> 1;

                tree[rt<<1].sum +=  1ll*tree[rt].lazy * (vec[mid] - vec[le-1]);
                tree[rt<<1|1].sum +=  1ll*tree[rt].lazy *(vec[ri] - vec[mid]);
                tree[rt].lazy = 0;
            }

            
            void update(int L, int R, int le, int ri, int rt) {
                if(le >= L && ri <= R) {
                    tree[rt].lazy++;
                    tree[rt].cnt++;
                    //因为每个节点表示【le实际值,ri实际值)的长度。
                    tree[rt].sum += 1ll*(vec[ri] - vec[le - 1]);
                    return;
                }
                int mid = (le + ri) >> 1;
                if(tree[rt].lazy) pushdown(le,ri,rt);
                if(mid >= L) {
                    update(L, R, le, mid, rt<<1);
                }
                if(mid < R) {
                    update(L, R, mid+1, ri, rt<<1|1);
                }
                tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
            }

            int query(ll tot, int le, int ri, int rt) {
                if(le == ri) {

                    int cnt = tree[rt].cnt, res;
                    int lbound = vec[le-1];
                    if(tot % cnt == 0) {
                        res = lbound + tot / cnt - 1;
                    }
                    else
                        res = lbound + tot / cnt;
                    return res;

                }
 
                int mid = (le + ri) >> 1;
                if(tree[rt].lazy) pushdown(le,ri,rt);
 
                ll lsum = tree[rt<<1].sum;
                if(lsum >= tot) return query(tot,le, mid, rt<<1);
                else return query(tot - lsum, mid+1, ri, rt<<1|1);
            }
int main(){
 
            int n;
            scanf("%d", &n);
            scanf("%d%d%d%d%d%d", &X[1], &X[2], &a1, &b1, &c1, &m1);
            scanf("%d%d%d%d%d%d", &Y[1], &Y[2], &a2, &b2, &c2, &m2);
            
            L[1] = min(X[1], Y[1]) + 1;
            R[1] = max(X[1], Y[1]) + 1;
            L[2] = min(X[2], Y[2]) + 1;
            R[2] = max(X[2], Y[2]) + 1;
            //因为我后面操作的是左闭右开区间,所以这里右端点++。
            R[1] ++; R[2] ++;
            vec.pb(L[1]);vec.pb(R[1] );
            vec.pb(L[2]);vec.pb(R[2]);
            for(int i=3; i<=n; i++) {
                X[i] = (1ll*a1 * X[i-1] + 1ll*b1 * X[i-2] + c1 )% m1;
                Y[i] = (1ll*a2 * Y[i-1] + 1ll*b2 * Y[i-2] + c2 )% m2;
                L[i] = min(X[i], Y[i]) + 1;
                R[i] = max(X[i], Y[i]) + 1;
                R[i] ++;
                vec.pb(L[i]);   vec.pb(R[i]);
            }
            sort(vec.begin(), vec.end());
            vec.erase(unique(vec.begin(), vec.end()), vec.end());
            for(int i=1; i<=n; i++) {
                L[i] = getid(L[i]);
                R[i] = getid(R[i]);
            }
            
            int tot = vec.size();

            ll all = 0;

            for(int i=1; i<=n; i++) {
                
                update(L[i], R[i] - 1, 1, tot, 1);

                all += 1ll*(vec[R[i]-1] - vec[L[i] - 1]);
                
                printf("%d
", query((all + 1)/2, 1, tot, 1));
            }
            return 0;
}
View Code

H Pair

题意

给定A,B,C($A le 1e9, B le 1e9, C le 1e9$),求满足

$$ (x & y) > C $$

$$ (x oplus y)  < C$$

的<x, y>对数。其中

$ 1 le x le A, 1 le y le B$

思路

数位DP,自己code了好久

/*
* @Author: chenkexing
* @Date:   2019-08-09 23:58:00
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-10 22:19:16
* @Link https://ac.nowcoder.com/acm/contest/887/H
*/
// #pragma GCC optimize(2)
//  #pragma GCC optimize(3)
//  #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
  
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
  
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
  
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
  
/**********showtime************/
ll dp[35][2][2][2][2][3][3];
//dp[len][limit1][limit2][ok1][ok2]
//由于两个数要大于0,所以多加上ok1,ok2.
//f1 &的, f2 ^的 // == 2 表示不行了
int shuA[35],shuB[35],shuC[35];
ll dfs(int len, int limit1, int limit2, int ok1, int ok2, int f1, int f2){
    if(f1 == 2 && f2 == 2) return 0;
    if(dp[len][limit1][limit2][ok1][ok2][f1][f2] != -1)
        return dp[len][limit1][limit2][ok1][ok2][f1][f2];
    if(len == 0) { 
        return ok1 && ok2 && (f1 == 1 || f2 == 1);
    }  

    int up1 = 1, up2 = 1;
    if(limit1) up1 = shuA[len];
    if(limit2) up2 = shuB[len];
    ll res = 0;
    // cout<<len<<" " << up1<<" , " << up2<<endl;
    for(int i=0; i<=up1; i++) {
        for(int j=0; j<=up2; j++) {
             
            // if(len == 2)cout<<len << " " << i << " , " << j << "  = " << f1 <<" , , " <<f2 << endl;

            if(f1 == 1 || f2 == 1) 
                res += dfs(len-1, limit1 && i == up1, limit2 && j == up2, ok1 || i, ok2 || j, f1, f2);
            else {
                int F1 = f1, F2 = f2;
                if((i & j) < shuC[len]) F1 = 2;
                else if((i & j) > shuC[len]) F1 = max(F1, 1);

                if((i ^ j) > shuC[len]) F2 = 2;
                else if((i ^ j) < shuC[len]) F2 = max(F2, 1);
                res += dfs(len-1, limit1 && i == up1, limit2 && j == up2, ok1 || i, ok2 || j, F1, F2);
            }  
        }

    }
    dp[len][limit1][limit2][ok1][ok2][f1][f2] = res;
    return res;
}
 
int main(){
    int T;  scanf("%d", &T);
    while(T--) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        memset(dp, -1, sizeof(dp));
        int len = 32;
        for(int i=1; i<=len; i++) shuA[i] = a % 2, a = a >> 1;
         for(int i=1; i<=len; i++) shuB[i] = b % 2, b = b >> 1;
        for(int i=1; i<=len; i++) shuC[i] = c % 2, c = c >> 1;
        printf("%lld
", dfs(len, 1, 1, 0, 0, 0, 0));
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ckxkexing/p/11322959.html