特殊做法类线段树

来源:互联网 发布:梦幻西游定心术算法 编辑:程序博客网 时间:2024/04/29 15:24
有一类神奇的线段树,我们来总结一下。。。。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COGS  1272 AHOI  行星序列
一道看起来很简单的线段树,有两种操作,包括*k,+a,但经过思考我们发现,但操作顺序不同时(先乘后加还是先加后乘),所以我们统一为一种操作(*k => *k+0  +a => *1+a) 于是水过。。。code:
#include<iostream>#include<cstdio>#include<cstring>#define mid (l+r)/2#define lch i<<1,l,mid#define rch i<<1|1,mid+1,rusing namespace std;long long node[400001],a[100001];int n,p,m;long long  delta[400001][2],ans;void updata(int i){node[i]=(node[i<<1]+node[i<<1|1])%p;}void build(int i,int l,int r){delta[i][0]=1;delta[i][1]=0;if (l==r)  {    node[i]=a[l]%p;    return;  }build(lch); build(rch);updata(i);}void paint(int i,int l,int r,long long k,long long a){int t;a=a%p;  k=k%p; t=(r-l+1)%p; node[i]=((node[i]*k)%p+(a*t)%p)%p;delta[i][0]=(delta[i][0]*k)%p;delta[i][1]=((delta[i][1]*k)%p+a)%p;}void pushdown(int i,int l,int r){paint(lch,delta[i][0],delta[i][1]);paint(rch,delta[i][0],delta[i][1]);delta[i][0]=1; delta[i][1]=0;}void insert(int i,int l,int r,int x,int y,long long a,int kind){if (x<=l&&y>=r)  {  if (kind==2)      paint(i,l,r,1,a);    if (kind==1)      paint(i,l,r,a,0);    return;  }pushdown(i,l,r);if (x<=mid) insert(lch,x,y,a,kind);if (y>mid) insert(rch,x,y,a,kind);updata(i);}void query(int i,int l,int r,int x,int y){if (x<=l&&y>=r)  {    ans=(node[i]+ans)%p;return;     }pushdown(i,l,r);if (x<=mid) query(lch,x,y);if (y>mid) query(rch,x,y);}int main(){freopen("seqb.in","r",stdin);freopen("seqb.out","w",stdout);int i,kind,t,g,c;scanf("%d%d",&n,&p);for (i=1;i<=n;++i) scanf("%d",&a[i]);build(1,1,n);scanf("%d",&m);for (i=1;i<=m;++i)  {    scanf("%d",&kind);    if (kind==1||kind==2)      {      c=c%p;        scanf("%d%d%d",&t,&g,&c);insert(1,1,n,t,g,c,kind);       }    if (kind==3)      {        scanf("%d%d",&t,&g);        ans=0; query(1,1,n,t,g);        printf("%lld\n",ans);      }  }fclose(stdin);fclose(stdout);}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COGS  三元数对&&数列
      统计在某数之前比某数小和某数之后比某数小(或大)的个数,思路很奇特,以数字为节点建树,然后在线单点修改,区间求值。。。
 三元数对(离散化)code
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define mid (l+r)/2#define lch i<<1,l,mid#define rch i<<1|1,mid+1,rusing namespace std;int node[200000],n;int a[30001],b[30001];int minn[30001];int ans;long long sum;void updata(int i){node[i]=node[i<<1]+node[i<<1|1];}void insert(int i,int l,int r,int x){if (l==r&&l==x)  {    node[i]+=1;    return;  }if (x<=mid) insert(lch,x);else insert(rch,x);updata(i);}void query(int i,int l,int r,int x,int y){if (x<=l&&y>=r)  {    ans+=node[i];return;       }if (x<=mid) query(lch,x,y);if (y>mid) query(rch,x,y);}int main(){int i,size;freopen("three.in","r",stdin);freopen("three.out","w",stdout);scanf("%d",&n);sum=0;for (i=1;i<=n;++i)  {    scanf("%d",&a[i]);    a[i]+=2;    b[i]=a[i];  }sort(b+1,b+n+1);size=unique(b+1,b+n+1)-b-1;for (i=1;i<=n;++i)    a[i]=upper_bound(b+1,b+size+1,a[i])-b;size++;memset(node,0,sizeof(node));for (i=1;i<=n;++i)  {    insert(1,1,size,a[i]);    if (i>1)      {        ans=0;        query(1,1,size,1,a[i]-1);        minn[i]=ans;      }  }memset(node,0,sizeof(node));for (i=n;i>=1;--i)  {    insert(1,1,size,a[i]);    if (i<n)      {        ans=0;        query(1,1,size,a[i]+1,size);        if (i>1)          sum+=ans*minn[i];      }  }printf("%lld\n",sum);fclose(stdin);fclose(stdout);}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TYVJ 1728 普通平衡树
一道著名的平衡树练习题,我们考虑它的线段树做法(做死了。。。),首先离散化(为了输出原数搞一个类似映射的东西),然后以数为节点建立线段树,然后blabla乱搞就好了(蒟蒻的算法常数很大,很大) code:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define mid (l+r)/2#define lch i<<1,l,mid#define rch i<<1|1,mid+1,rusing namespace std;int node[400001],n;struct hp{int kind,x;}opt[100001];int b[100001];int f[100001],ans,rank,ansi;void updata(int i){node[i]=node[i<<1]+node[i<<1|1];}void insert(int i,int l,int r,int x,int a){if (l==r&&l==x)  {    node[i]+=a;    return;  }if (x<=mid) insert(lch,x,a);else insert(rch,x,a);updata(i);}void querynum(int i,int l,int r,int x){if (l==r&&l==x)  {ansi=i; ans++; return;}if (x<=mid)  querynum(lch,x);else  {  ans+=node[i<<1];    querynum(rch,x);  }}void queryx(int i,int l,int r,int x){if (l==r&&rank<=x&&rank+node[i]>=x)  {    ans=l;return;   } if (rank+node[i<<1]>=x)  queryx(lch,x);else  {    rank+=node[i<<1];queryx(rch,x);   } }int main(){int t,i,size;freopen("phs.in","r",stdin);freopen("phs.out","w",stdout);scanf("%d",&n);for (i=1;i<=n;++i)  {    scanf("%d%d",&opt[i].kind,&opt[i].x);    b[i]=opt[i].x;  }sort(b+1,b+n+1);size=unique(b+1,b+n+1)-b-1;for (i=1;i<=n;++i)  {    t=lower_bound(b+1,b+size+1,opt[i].x)-b;f[t]=opt[i].x;opt[i].x=t;    }for (i=1;i<=n;++i)  {        if (opt[i].kind==1)          insert(1,1,size,opt[i].x,1);        if (opt[i].kind==2)          insert(1,1,size,opt[i].x,-1);        if (opt[i].kind==3)           {            ans=0;            querynum(1,1,size,opt[i].x);            printf("%d\n",ans);          }        if (opt[i].kind==4)          {          rank=0;             queryx(1,1,size,f[opt[i].x]);            printf("%d\n",f[ans]);           }        if (opt[i].kind==5)          {          ans=0;          querynum(1,1,size,opt[i].x);            rank=0;            queryx(1,1,size,ans-1);            printf("%d\n",f[ans]);          }        if (opt[i].kind==6)          {    ans=0;             querynum(1,1,size,opt[i].x);            rank=0;             queryx(1,1,size,ans+node[ansi]);            printf("%d\n",f[ans]);          }  }fclose(stdin);fclose(stdout);}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                                                                                                                                                  Lcomyn
0 0