您的位置:首页 > 其它

(线段树)湖南省第八届ACM省赛 RMQ with Shifts

2014-08-11 15:59 411 查看
  RMQ with Shifts

题意:这题题意还是比较简单,主要有两种操作:

1.query一个闭区间的最小值;

2.将一组数据左移一次!直接更新叶子节点的值即可(字符串长度最多为30,故更新操作最多不超过12次)!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define LL long long
#define M 100005
#define DEBUG puts("It's here!")
#define INF 1<<29
#define kind 30
#define CLS(x,v) memset(x,v,sizeof(x))
#define FOR(i,a,n)  for(int i=(a);i<=(n);++i)

struct node
{
int l,r,minn;
node*lef,*rig;
} q[M<<1];
int n,a[M],cnt;
char s[50];
int ans,data[30];
//建立线段树
void BuildSeg(node *p,int l,int r)
{
p->l=l;
p->r=r;
if(l==r)p->minn=a[l];
if(l<r)
{
p->lef=q+cnt;
cnt++;
BuildSeg(p->lef,l,(l+r)>>1);
p->rig=q+cnt;
cnt++;
BuildSeg(p->rig,(l+r)/2+1,r);
p->minn=min(p->lef->minn,p->rig->minn);
}
}
void query(node *p,int l,int r)
{
if(p->l==l&&p->r==r)
{
ans=min(ans, p->minn);
return ;
}
if(r<=(p->l+p->r)/2)
query(p->lef,l,r);
else if(l>(p->l+p->r)/2)
query(p->rig,l,r);
else
{
query(p->lef,l,(p->l+p->r)/2);
query(p->rig,(p->l+p->r)/2+1,r);
}
}
void update(node *p,int x)
{
p->minn=INF;
if(p->l==x&&p->r==x)
{
p->minn=a[x];
return ;
}
if(x<=(p->l+p->r)/2)update(p->lef,x);
else update(p->rig,x);
p->minn=min(p->lef->minn,p->rig->minn);
}
void deal()
{
int k=0;
data[0]=0;
for(int i=5;s[i];i++)
if(s[i]>'0'&&s[i]<='9')
{
k=++data[0];
data[k]=0;
while(s[i]>='0'&&s[i]<='9')
{
data[k]=data[k]*10+(s[i]-'0');
i++;
}
}
}
int main()
{
int k;
char c;
while(~scanf("%d%d",&n,&k))
{
for(int i=1; i<=n; i++)
scanf("%d",a+i);
node *root=q;
cnt=1;
BuildSeg(root,1,n);
while(k--)
{
scanf("%s",s);
deal();
if(s[0]=='q')
{
ans=INF;
query(root,data[1],data[2]);
printf("%d\n",ans);
}
else if(s[0]=='s')
{
for(int i=1;i<data[0];i++)
{
swap(a[data[i]],a[data[i+1]]);
update(root,data[i]);
}
update(root,data[data[0]]);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: