「杂题乱刷2」P11843 [USACO25FEB] The Best Subsequence G

题目链接

P11843 [USACO25FEB] The Best Subsequence G

题意简述

有一个长度为 n 的初始全为 0 的数列,现在有 m 次将 lr 区间内的所有数字都取反的操作。

q 次询问,每次询问形如 l r x,你需要找出 lr 中字典序最大的长度为 x 的子序列。

每次询问只需要输出这个子序列在二进制下拼接而成的数字转为十进制的数字,对 109+7 取模。

1n1091m2×1051q2×105

解题思路

在线做法。

发现这个问题可以转化为初始全为 1 的字符串,询问变为找字典序最小的字符串,那么设这个字典序最小的子序列转化为十进制下的数字为 ans,由于你发现两种决策一致,那么答案即为 2x1ans

那么我们考虑最小字典序怎么做。

你发现首先由于翻转次数只有 m 次,那么显然将连续段合并后总共只有 2m 个区间,此处离散化即。

那么我们考虑此时怎样查询,发现答案前缀全选 0 总是最优的,那么显然答案的后面选取的是 lr 中的一个后缀,不然如果有更优的前缀肯定可以多选一个 0,那么是一定能二分到的,那么我们只需要考虑取二分最后一个能取的前缀 0 的位置即可。

那么考虑如何查询后缀的值,你发现这跟本质一致,那么只需要处理前后两个散块即可,中间的块线段树维护即可。

时间复杂度 O(qlognlogm)

参考代码

#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define cll const ll
#define forl(i,a,b) for(re ll (i)=(a);i<=(b);(i)++)
#define forr(i,a,b) for(re ll (i)=(a);i>=(b);(i)--)
#define forll(i,a,b,c) for(re ll (i)=(a);i<=(b);(i)+=(c))
#define forrr(i,a,b,c) for(re ll (i)=(a);i>=(b);(i)-=(c))
#define pii pair<ll,ll>
#define mid (((l)+(r))>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) (1ll*(x)/__gcd(x,y)*(y))
#define Sum(x,y) (1ll*((x)+(y))*((y)-(x)+1)/2)
#define x first
#define y second
#define maxqueue priority_queue<ll>
#define minqueue priority_queue<ll,vector<ll>,greater<ll>>
#define bug1 cout<<"bug1,AWaDa?\n";
#define bug2 cout<<"bug2,AWaDa!\n";
#define bug3 cout<<"bug3,AKTang?\n";
#define bug4 cout<<"bug4,AKTang!\n";
#define IM (ll)1e9
#define LM (ll)1e18
#define MIM (ll)-1e9
#define MLM (ll)-1e18
#define sort stable_sort
ll pw(ll x,ll y,ll mod){if(y==0)return 1;if(x==0)return 0;ll an=1,tmp=x;while(y){if(y&1)an=(an*tmp)%mod;tmp=(tmp*tmp)%mod;y>>=1;}return an;}
ll pw(ll x){return 1ll<<x;}
template<typename T1,typename T2>bool Max(T1&x,T2 y){if(y>x)return x=y,1;return 0;}template<typename T1,typename T2>bool Min(T1&x,T2 y){if(y<x)return x=y,1;return 0;}ll Ss=chrono::steady_clock::now().time_since_epoch().count();mt19937_64 Apple(Ss);ll rand_lr(ll l,ll r){return Apple()%(r-l+1)+l;}
cll mod=1e9+7,N=300010;ll fac[N],inv[N];void init(){fac[0]=1;forl(i,1,N-5)fac[i]=i*fac[i-1],fac[i]%=mod;inv[N-5]=pw(fac[N-5],mod-2,mod);forr(i,N-5,1)inv[i-1]=inv[i]*i%mod;}ll C(ll n,ll m){if(n<m || m<0)return 0;return (fac[n]%mod)*(inv[n-m]*inv[m]%mod)%mod;}
ll _t_;
ll lg[1000010];
void Init(){
	forl(i,2,1e6+5)
		lg[i]=lg[i>>1]+1;
}
ll n,m,q;
map<ll,ll>mp1,mp2;
vector<ll>G;
struct node{
    ll l,r,tag;
}a[1000010];
ll lst,k,num;
void _clear(){}
/*
10101
*/
ll pre[1000010];
ll _0(ll l,ll r){
    return (a[r].r-a[l].l+1)-(pre[r]-pre[l-1]);
}
ll _1(ll l,ll r){
    return pre[r]-pre[l-1];
}
ll f(ll l,ll r){
    return a[r].r-a[l].l+1;
}
ll l,r,x;
ll pos(ll x)
{
    ll L=1,R=k;
    while(L<R)
    {
        ll Mid=(L+R+1)/2;
        if(x<a[Mid].l)
            R=Mid-1;
        else
            L=Mid;
    }
    return L;
}
ll __0(ll l,ll r)
{
    if(l>r)
        return 0;
    ll id1=pos(l),id2=pos(r);
    if(id1==id2)
    {
        if(a[id1].tag==0)
            return r-l+1;
        return 0;
    }
    ll S=0;
    if(a[id1].tag==0)
        S+=a[id1].r-l+1;
    if(a[id2].tag==0)
        S+=r-a[id2].l+1;
    id1++,id2--;
    if(id1<=id2)
        S+=_0(id1,id2);
   // cout<<"__0("<<l<<','<<r<<")="<<S<<','<<x<<endl;
    return S;
}
struct SegTree{
    struct node{
        ll l,r,len,val;
    }tree[4000010];
    void pushup(ll x)
    {
        tree[x].len=(tree[x*2].len+tree[x*2+1].len);
        tree[x].val=(tree[x*2].val*pw(2,tree[x*2+1].len,mod)%mod+tree[x*2+1].val)%mod;
    }
    void build(ll x,ll l,ll r)
    {
        // cout<<"abc "<<x<<" "<<l<<" "<<r<<endl;
        tree[x]={l,r,0,0};
        if(l==r)
        {
            tree[x].len=a[l].r-a[l].l+1;
            if(a[l].tag)
                tree[x].val=(pw(2,tree[x].len,mod)-1+mod)%mod;
            else
                tree[x].val=0;
            // cout<<x<<' '<<tree[x].val<<' '<<tree[x].len<<endl;
            return ;
        }
        build(x*2,l,mid);
        build(x*2+1,mid+1,r);
        pushup(x);
    }
    // ll query(ll x,ll l,ll r)
    // {
    //     if(l<=tree[x].l && tree[x].r<=r)
    //         return tree[x].val;
    //     ll Mid=(tree[x].l+tree[x].r)/2;
    //     if(r<=Mid)
    //         return query(x*2,l,r);
    //     if(Mid<l)
    //         return query(x*2+1,l,r);
    //     return (query(x*2,l,r)*pw(2,r-tree[x*2+1].l+1,mod)%mod+query(x*2+1,l,r))%mod;
    // }
    ll query(ll x,ll l,ll r)
    {
        if(l<=tree[x].l && tree[x].r<=r)
        {
            // cout<<"cde "<<tree[x].l<<" "<<tree[x].r<<endl;
            // cout<<tree[x].val<<" "<<pw(2,a[r].r-a[tree[x].r].r,mod)<<endl;
            return tree[x].val*pw(2,a[r].r-a[tree[x].r].r,mod)%mod;
        }
        ll Mid=(tree[x].l+tree[x].r)/2;
        if(r<=Mid)
            return query(x*2,l,r)%mod;
        if(Mid<l)
            return query(x*2+1,l,r)%mod;
        return (query(x*2,l,r)+query(x*2+1,l,r))%mod;
    }
}T;
/*
10101
01010

1011

15 - 11 = 4
*/
ll query(ll l,ll r)
{
    ll id1=pos(l),id2=pos(r);
    if(id1==id2)
    {
     //   cout<<"brute:";
        if(a[id1].tag==0)
            return 0;
        return (pw(2,r-l+1,mod)-1+mod)%mod;
    }
    ll num=0;
    if(a[id2].tag)
        num+=pw(2,(r-a[id2].l+1),mod)-1+mod;
    num%=mod;
    // cout<<"awa"<<(pw(2,(r-a[id2].l+1),mod)-1+mod)%mod<<endl;
    if(id1+1<=id2-1)
        num+=T.query(1,id1+1,id2-1)*pw(2,r-a[id2-1].r,mod)%mod;
    num%=mod;
    // cout<<"qwq"<<T.query(1,id1+1,id2-1)<<endl;
    if(a[id1].tag)
        num+=((pw(2,a[id1].r-l+1,mod)-1+mod)%mod*pw(2,r-a[id1].r,mod))%mod;
    // cout<<"OvO"<<((pw(2,a[id1].r-l+1,mod)-1+mod)%mod*pw(2,r-a[id1].r,mod))%mod<<endl;
    return num;
}
/*
01110

3 - 2 = 1

00110110

31 - 16 - 4 - 2 = 9

11011001


*/
void solve()
{
    _clear();
    cin>>n>>m>>q;
    forl(i,1,m)
        cin>>l>>r,
        G.pb(l),
        G.pb(r+1);
    sort(G.begin(),G.end());
    ll L=0,sz=(ll)G.size()-1;
    lst=1;
    num=1;
    forl(i,0,(ll)G.size()-1)
    {
        ll l=num;
        num^=1;
        while(i<sz && G[i]==G[i+1])
            i++,
            num^=1;
        if(num==l)
            continue;
        if(lst<=G[i]-1)
            a[++k]={lst,G[i]-1,l},
            lst=G[i];
    }
    if(lst<=n)
        a[++k]={lst,n,num};
  //  forl(i,1,k)
  //      cout<<a[i].l<<' '<<a[i].r<<' '<<a[i].tag<<endl;
    forl(i,1,k)
        pre[i]=pre[i-1]+a[i].tag*(a[i].r-a[i].l+1);
    T.build(1,1,k);
   // if(n==9)
   //     cout<<pos(7)<<' '<<pos(8)<<endl;
    //cout<<T.query(1,1,5)<<endl;
    forl(_,1,q)
    {
        cin>>l>>r>>x;
        ll id1=pos(l),id2=pos(r);
        if(id1==id2)
        {
       //    cout<<a[id1].tag<<endl;
           // cout<<0<<endl;
            if(a[id1].tag==0)
                cout<<(pw(2,x,mod)-1+mod)%mod<<endl;
            else
                cout<<0<<endl;
            continue;
        }
//        cout<<
        if(__0(l,r)>=x)
        {
           // cout<<0<<endl;
            cout<<(pw(2,x,mod)-1+mod)%mod<<endl;
            continue;
        }
        ll L=l-1,R=r;
        while(L<R)
        {
            ll Mid=(L+R+1)/2;
            if(__0(l,Mid)+(r-Mid)>=x)
                L=Mid;
            else
                R=Mid-1;
        }
//        cout<<"<"<<L<<'>';
        if(L+1<=r)
         //   cout<<"?\n",
            cout/*<<"query("<<L+1<<','<<r<<")="*/<<((((pw(2,x,mod)-1+mod)%mod)-query(L+1,r))%mod+mod)%mod<<endl;
        else
            cout<<0<<endl;
    }
}
int main()
{
	Init();
//    freopen("tst.txt","r",stdin);
//    freopen("sans.txt","w",stdout);
    IOS;
    _t_=1;
  // cin>>_t_;
    while(_t_--)
        solve();
    QwQ;
}
posted @   wangmarui  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
历史上的今天:
2024-03-03 「杂题乱刷」洛谷 P4801
2024-03-03 「杂题乱刷」CF1934D2
点击右上角即可分享
微信分享提示