【刷题】【数据结构】【树状数组】【线段树】

1>数星星

(复制自他人博客)

由于题目中给的数据是按y轴排序,我们只需构建x轴的树状数组,也就是说我们只需统计星星i之前一共有多少个x坐标小于或等于Xi的星星,这个数值也就是星星i的等级

又因为树状数组无法处理下标为0的元素(会死循环),所以要把每个x坐标+1

#include
#include
#include
using namespace std;
int max(int a,int b)
{ return a>b ?a :b; }
int n,mx;
const int N=15003,M=33000;
struct node
{
    int x,y,xh;
    bool operator < (const node & o) const
    { return x!=o.x ?xo.y; }
}d[N];
int ans[N],cnt[N];

int tr[M];
int lowbit(int x)
{ return x&(-x); }
void add(int pos)
{
    while(pos<=mx) 
        tr[pos]++,pos+=lowbit(pos);
}
int query(int pos)
{
    int ans=0;
    while(pos>0)
        ans+=tr[pos],pos-=lowbit(pos);
    return ans;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&d[i].x ,&d[i].y ),d[i].xh =i,
        d[i].x ++,d[i].y ++,mx=max(mx,d[i].y );
    sort(d+1,d+n+1);
    
    for(int i=1;i<=n;i++)
    {
        ans[d[i].xh ]=query(d[i].y );
        add(d[i].y );
        cnt[ans[d[i].xh ]]++;
    }
    
    for(int i=0;i"%d\n",cnt[i]);
    return 0;
}

 2>花神游历各国

小清新线段树

有点像 普通线段树 + 剪枝

一般题面会有一个神奇的(暂且这么说)更改方式,而且一般没办法区间更新出值

 

这里是一个数的多次开方,可以发现,开方此时应该是有限的,<=1时不再变化

当区间最大值<=1时,整个区间都不再变化

#include
#include
#include
#define ll long long
using namespace std;
ll max(ll a,ll b)
{ return a>b ?a :b; }
const int N=100003;
int n;ll d[N];int m;

int root,cnt;
struct node
{
    int lson,rson;
    ll sum,mx;
}tr[N<<1];
void updata(int rt)
{
    tr[rt].sum =tr[tr[rt].lson ].sum +tr[tr[rt].rson ].sum ;
    tr[rt].mx = max(tr[tr[rt].lson ].mx ,tr[tr[rt].rson ].mx );
}
void build(int &rt,int l,int r)
{
    rt=++cnt;
    if(l==r)
    {
        tr[rt].sum =tr[rt].mx =d[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(tr[rt].lson ,l,mid);
    build(tr[rt].rson ,mid+1,r);
    updata(rt);
}
int ql,qr;
void change(int rt,int l,int r)
{
    if(tr[rt].mx <=1) return ;
    if(l==r )
    {
        tr[rt].sum =tr[rt].mx =sqrt(tr[rt].sum );
        return ;
    }
    int mid=(l+r)>>1;
    if(ql<=mid ) change(tr[rt].lson ,l,mid);
    if(qr> mid ) change(tr[rt].rson ,mid+1,r);
    updata(rt);
}
ll query(int rt,int l,int r)
{
    if(ql<=l && qr>=r) return tr[rt].sum ;
    int mid=(l+r)>>1;
    
    if(qr<=mid) return query(tr[rt].lson ,l,mid);
    else if(ql>mid) query(tr[rt].rson ,mid+1,r);
    else return query(tr[rt].lson ,l,mid)+query(tr[rt].rson ,mid+1,r);
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&d[i]);
    build(root,1,n);
    
    int op;
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d%d%d",&op,&ql,&qr);//简化搜索次数,否则tle 
        if(ql>qr) 
        {
            int t=ql;
            ql=qr,qr=t;
        }
        if(op==1)
            printf("%lld\n",query(1,1,n));
        else
            change(1,1,n);
    }
    
    return 0;
}

 

你可能感兴趣的:(【刷题】【数据结构】【树状数组】【线段树】)