hdu5634 BestCoder Round #73 (div.1) Rikka with Phi 解题报告

来源:互联网 发布:网络免费小说一号红人 编辑:程序博客网 时间:2024/06/05 08:54

题意:

给一个序列,3种操作,一个区间全部赋值为x,一个区间内的每个ai 变成 phi(ai),询问一个区间的和






题解:

怎么说呢,这种每个数变成他的 phi() , 开根什么的,一般来说都是要一个个修改的,但是一个数 ai,你不断对他取phi,开根什么的,经过log2ai次都会变成1,而当一个区间的数都相同时,你就可以对他区间开根或者取phi了,所以这题用一个线段树维护区间和和标记,当区间内的所有数相同时就直接在这个节点更新,不然就递归下去
时间复杂度的话,大概是 nlog2n



code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<ctime>#include<ctime>#include<vector>#include<string>#include<bitset>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int maxn = 310000;const int maxp = 10000010;int pri[maxp/10],prime;int phi[maxp];struct node{    ll sum;    int c;}tr[maxn<<2];int a[maxn];int n,m;void pushdown( int x,int l,int r ){    int mid = ( l+r )>>1, lc = x<<1, rc = lc|1;    if( tr[x].c == -1 ) return ;    if( tr[x].c != tr[lc].c )    {        tr[lc].c = tr[x].c;        tr[lc].sum = (ll)tr[x].c*(mid-l+1);    }    if( tr[x].c != tr[rc].c )    {        tr[rc].c = tr[x].c;        tr[rc].sum = (ll)tr[x].c*(r-mid);    }}void build_( int x,int l,int r ){    if( l == r )    {        tr[x].sum = tr[x].c = a[l];        return ;    }    int mid = ( l+r )>>1, lc=  x<<1, rc = lc|1;    build_( lc,l,mid ); build_( rc,mid+1,r );    tr[x].sum = tr[lc].sum + tr[rc].sum;    tr[x].c = tr[lc].c == tr[rc].c ? tr[lc].c : -1;}void tphi( int x,int l,int r ){    if( l == r || tr[x].c != -1 )    {        tr[x].c = phi[tr[x].c];        tr[x].sum = (ll)tr[x].c*(r-l+1);        return ;    }    int mid = ( l+r )>>1, lc = x<<1, rc=  lc|1;    tphi( lc,l,mid ); tphi( rc,mid+1,r );    tr[x].sum = tr[lc].sum + tr[rc].sum;    tr[x].c = tr[lc].c == tr[rc].c ? tr[lc].c : -1;}void update( int x,int l,int r,int lx,int rx ){    if( lx <= l && r <= rx )    {        tphi( x,l,r );        return ;    }    pushdown( x,l,r );    int mid = ( l+r )>>1, lc = x<<1, rc = lc|1;    if( rx <= mid ) update( lc,l,mid,lx,rx );    else if( lx > mid ) update( rc,mid+1,r,lx,rx );    else    {        update( lc,l,mid,lx,mid );        update( rc,mid+1,r,mid+1,rx );    }    tr[x].sum = tr[lc].sum + tr[rc].sum;    tr[x].c = tr[lc].c == tr[rc].c ? tr[lc].c : -1;}void change( int x,int l,int r,int lx,int rx,int c ){    if( lx <= l && r <= rx )    {        tr[x].c = c;        tr[x].sum = (ll)c*(r-l+1);        return ;    }    pushdown( x,l,r );    int mid = ( l+r )>>1, lc = x<<1,  rc = lc|1;    if( rx <= mid ) change( lc,l,mid,lx,rx,c );    else if( lx > mid ) change( rc,mid+1,r,lx,rx,c );    else    {        change( lc,l,mid,lx,mid,c );        change( rc,mid+1,r,mid+1,rx,c );    }    tr[x].sum = tr[lc].sum + tr[rc].sum;    tr[x].c = tr[lc].c == tr[rc].c ? tr[lc].c : -1;}ll Query( int x,int l,int r,int lx,int rx ){    if( lx <= l && r <= rx ) return tr[x].sum;    pushdown( x,l,r );    int mid = ( l+r )>>1, lc = x<<1, rc= lc|1;    if( rx <= mid ) return Query( lc,l,mid,lx,rx );    else if( lx > mid ) return Query( rc,mid+1,r,lx,rx );    else return Query( lc,l,mid,lx,mid ) + Query( rc,mid+1,r,mid+1,rx );}int main(){    int t;    int x,y,c;    prime = 0;    for( int i=1;i<maxp;i++ ) phi[i] = i;    for( int i=2;i<maxp;i++ )    {        if( phi[i] == i )        {            pri[++prime] = i;            phi[i] = i-1;        }        for( int j=1;j<=prime;j++ )        {            int k = i*pri[j];            if( k >= maxp ) break;            if( (i%pri[j]) == 0 )            {                       phi[k] = phi[i]*pri[j];                break;            }            phi[k] = phi[i]*phi[pri[j]];        }    }    scanf("%d",&t);    while( t-- )    {        scanf("%d%d",&n,&m);        for( int i=1;i<=n;i++ ) scanf("%d",&a[i]);        build_( 1,1,n );        while( m-- )        {            scanf("%d",&x);            if( x == 1 )            {                scanf("%d%d",&x,&y);                update( 1,1,n,x,y );            }            else if( x == 2 )            {                scanf("%d%d%d",&x,&y,&c);                change( 1,1,n,x,y,c );            }            else            {                scanf("%d%d",&x,&y);                printf("%I64d\n",Query( 1,1,n,x,y ));            }        }    }    return 0;}
0 0
原创粉丝点击