Josephus Transform(约瑟夫变换 线段树)

https://ac.nowcoder.com/acm/contest/5671/J
Josephus Transform(约瑟夫变换 线段树)_第1张图片
题意:

每次操作对序列做,X次K约瑟夫环变换,问最终序列。
一次3约瑟夫环变化后,12345变成31524,就是每数3个数后删掉。

解析:

求出一次变换的结果:

线段树,tr记录sum,当前pos的前缀和为val,下一个就是第一个大于等于val+k的位置。

一次求出来后K次相当于找出环,X%环长后就是这个环转置的次数。

代码:

#include
using namespace std;
typedef long long ll;typedef double db;
typedef pair<int, int> pii;typedef pair<ll, ll> pll;
typedef pair<int,ll> pil;typedef pair<ll,int> pli;
#define Fi first
#define Se second
#define _Out(a) cerr<<#a<<" = "<<(a)<
const int INF = 0x3f3f3f3f, MAXN = 2e5 + 50;
const ll LINF = 0x3f3f3f3f3f3f3f3f, MOD = 998244353;
const db Pi = acos(-1), EPS = 1e-6;
void test(){cerr << "\n";}template<typename T,typename...Args>void test(T x,Args...args){cerr<<x<<" ";test(args...);}
inline ll qpow(ll a, ll b){return b?((b&1)?a*qpow(a*a%MOD,b>>1)%MOD:qpow(a*a%MOD,b>>1))%MOD:1;}
inline ll qpow(ll a, ll b,ll c){return b?((b&1)?a*qpow(a*a%c,b>>1,c)%c:qpow(a*a%c,b>>1,c)) %c:1;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll cede(ll a,ll b){if(b<0)return cede(-a,-b);if(a<0)return a/b;return (a+b-1)/b;}
inline ll flde(ll a,ll b){if(b<0)return flde(-a,-b);if(a<0)return (a-b+1)/b;return a/b;}
inline int sign(db x){return x<-EPS ? -1:x>EPS;}
inline int dbcmp(db l,db r){return sign(l - r);}
namespace Fast_IO{ //orz laofu
    const int MAXL((1 << 18) + 1);int iof, iotp;
    char ioif[MAXL], *ioiS, *ioiT, ioof[MAXL],*iooS=ioof,*iooT=ioof+MAXL-1,ioc,iost[55];
    char Getchar(){
        if (ioiS == ioiT){
            ioiS=ioif;ioiT=ioiS+fread(ioif,1,MAXL,stdin);return (ioiS == ioiT ? EOF : *ioiS++);
        }else return (*ioiS++);
    }
    void Write(){fwrite(ioof,1,iooS-ioof,stdout);iooS=ioof;}
    void Putchar(char x){*iooS++ = x;if (iooS == iooT)Write();}
    inline int read(){
        int x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
        if(ioc==EOF)Write(),exit(0);
        for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
    }
    inline long long read_ll(){
        long long x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
        if(ioc==EOF)Write(),exit(0);
        for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
    }
    void Getstr(char *s, int &l){
        for(ioc=Getchar();ioc==' '||ioc=='\n'||ioc=='\t';)ioc=Getchar();
        if(ioc==EOF)Write(),exit(0);
        for(l=0;!(ioc==' '||ioc=='\n'||ioc=='\t'||ioc==EOF);ioc=Getchar())s[l++]=ioc;s[l] = 0;
    }
    template <class Int>void Print(Int x, char ch = '\0'){
        if(!x)Putchar('0');if(x<0)Putchar('-'),x=-x;while(x)iost[++iotp]=x%10+'0',x/=10;
        while(iotp)Putchar(iost[iotp--]);if (ch)Putchar(ch);
    }
    void Putstr(const char *s){for(int i=0,n=strlen(s);i<n;++i)Putchar(s[i]);}
} // namespace Fast_IO
using namespace Fast_IO;
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
const int maxn=2e5+9;
int a[maxn];
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define root int rt,int l,int r
#define lson ls,l,mid
#define rson rs,mid+1,r
int tr[maxn<<2];
void build(root){
    if(l==r){
        tr[rt]=1;
        return;
    }
    build(lson);build(rson);
    tr[rt]=tr[ls]+tr[rs];
}
void update(root,int pos,int val){
    if(l==r){
        tr[rt]+=val;
        return;
    }
    if(pos<=mid)
        update(lson,pos,val);
    else
        update(rson,pos,val);
    tr[rt]=tr[ls]+tr[rs];
}
int queryPre(root,int pos){
    if(l==r){
        return tr[rt];
    }
    int ans=0;
    if(pos>mid)
        ans=tr[ls]+queryPre(rson,pos);
    else
        ans=queryPre(lson,pos);
    return ans;
}
 
int queryLowerbound(root,int value){
    if(l==r)return l;
    if(tr[ls]>=value)
        return queryLowerbound(lson,value);
    else
        return queryLowerbound(rson,value-tr[ls]);
}
 
void Once(int n,int k){
    build(1,1,n);
    int val=0;
    rep(i,1,n){
        int K=k;
        int pos;
        if(val!=0 && val+K>tr[1]){
            K-=tr[1]-val;
        }
        else{
            K=val+K;
        }
        K%=tr[1];
        if(K==0)K=tr[1];
        pos=queryLowerbound(1,1,n,K);
 
        a[i]=pos;
        update(1,1,n,pos,-1);
        val=queryPre(1,1,n,pos);
    }
//    rep(i,1,n){
//        printf("%d%c",a[i]," \n"[i==n]);
//    }
}
 
const int N=2e5+50;
int tmpH[N],huan[N];
bool vis[MAXN];
void change(int *arr,int len,int x)// indexed from 1 to len
{
    for(int i=1;i<=len;i++)vis[i]=0;
 
    for(int i=1;i<=len;i++)
    {
        if(vis[i])continue;
        int now=i,nxt=arr[i],cntH=0;
        vis[now]=1;huan[cntH++]=now;
        while(!vis[nxt])
        {
            huan[cntH++]=nxt;
            now=nxt;nxt=arr[now];vis[now]=1;
        }
        int QAQ=x%cntH;
        for(int j=0;j<cntH;j++)tmpH[huan[j]]=huan[(j+QAQ)%cntH];
    }
 
    for(int i=1;i<=len;i++)arr[i]=tmpH[i];
}
int changa(int *arr,int len)
{
    for(int i=1;i<=len;i++)
    {
        tmpH[arr[i]]=i;
    }
    for(int i=1;i<=len;i++)arr[i]=tmpH[i];
}
int changc(int *arr,int *brr,int len)
{
    for(int i=1;i<=len;i++)tmpH[brr[i]]=arr[i];
    for(int i=1;i<=len;i++)arr[i]=tmpH[i];
}
int now[MAXN];
void work()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)now[i]=i;
    for(int i=1;i<=m;i++)
    {
        int k,x;scanf("%d%d",&k,&x);
        Once(n,k);
       // printf("GETa :");for(int j=1;j<=n;j++)printf("%d%c",a[j]," \n"[j==n]);
        changa(a,n);
        //printf("changa :");for(int j=1;j<=n;j++)printf("%d%c",a[j]," \n"[j==n]);
        //for(int i=1;i<=n;i++)tmpnow[i]=a[i];
        //changc(now,a,n);
       // printf("changc :");for(int j=1;j<=n;j++)printf("%d%c",now[j]," \n"[j==n]);
        change(a,n,x);
       // printf("change :");for(int j=1;j<=n;j++)printf("%d%c",a[j]," \n"[j==n]);
        changc(now,a,n);
        //printf("change :");for(int j=1;j<=n;j++)printf("%d%c",now[j]," \n"[j==n]);
    }
    for(int i=1;i<=n;i++)printf("%d%c",now[i]," \n"[i==n]);
}
int main()
{
    //std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    //int T=read();for(int cas=1;cas<=T;cas++)
    //int T;scanf("%d",&T);for(int i=1;i<=T;i++)
        work();
   // Write();
}

你可能感兴趣的:(Josephus Transform(约瑟夫变换 线段树))