Gym - 101889D:Daunting device (老司机树)

题意:N个格子排出一排,开始格子颜色都是1;现在有M个操作:

           或,把区间[L,R]颜色改为c;

           或,查询一共有多少格子颜色为c。

           最后求颜色最多的数量。

数据是随机的,且强制在线。

思路:ODT裸题。维护相同颜色的区间。  split拆分区间,assign操作收缩区间,由于数据随机,区间的个数趋近于log级别。

注意split的时候先split(R+1),再split(L);因为这个我wa20了;在这里有写。 大概就是会改变指针啥的,我对iterator不了解,所以不知道,记下来好了。

这个在大量区间操作的题目中,如果说明了随机的,或者想试一试的情况下,还是非常优秀(暴力)的。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
struct in{
    int L,R,v;
    in(){}
    in(int LL,int RR,int vv):L(LL),R(RR),v(vv){}
    friend bool operator<(in a,in b){
        if(a.L==b.L) return a.R<b.R;
        return a.L<b.L;
    }
};
set<in>s;
#define IT set<in>::iterator
int num[100010],ans;
IT split(int pos)
{
    IT it=s.lower_bound(in(pos,-2,-2));
    if(it!=s.end()&&(*it).L==pos) return it;
    it--;
    int l=(*it).L,r=(*it).R,v=(*it).v;
    s.erase(it);
    s.insert(in(l,pos-1,v));
    return s.insert(in(pos,r,v)).first;
}
void Assign(int L,int R,int X)
{
    IT it2=split(R+1),it1=split(L);
    for(IT it=it1;it!=it2;it++) {
        num[(*it).v]-=((*it).R-(*it).L+1);
    }
    s.erase(it1,it2);
    s.insert(in(L,R,X));
    num[X]+=R-L+1;
}
int main()
{
    int N,L,C,P,X,A,B,S;
    scanf("%d%d%d",&L,&C,&N);
    s.insert(in(0,L-1,1)); num[1]=L;
    rep(i,1,N){
        scanf("%d%d%d%d",&P,&X,&A,&B); A%=L; B%=L;
        S=num[P]%L;
        int l=(A+1LL*S*S%L)%L,r=(A+1LL*(S+B)*(S+B)%L)%L;
        Assign(min(l,r),max(l,r),X);
    }
    rep(i,1,C) ans=max(ans,num[i]);
    printf("%d\n",ans);
    return 0;
}

 

It is your time to fight!
posted @ 2019-02-17 19:27  nimphy  阅读(548)  评论(0编辑  收藏  举报