线段树专题

poj1151 矩形面积并      离散化+排序+扫描线

int NUM,FLAG;
double BIT; //long long    float
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define cind(j) {   \
    BIT=0.1; j=FLAG=0; NUM=getchar();   \
    while(!DIG(NUM)&&NUM!='-'&&NUM!='.')NUM=getchar();   \
    if(NUM=='-'){FLAG=1;NUM=getchar();}   \
    if(DIG(NUM)){   \
        j=NUM-'0';NUM=getchar();   \
        while(DIG(NUM)){j=10*j+(NUM-'0');NUM=getchar();}   \
    }   \
    if(NUM=='.'){   \
        NUM=getchar();   \
        while(DIG(NUM)){j+=(NUM-'0')*BIT;BIT/=10;NUM=getchar();}   \
    }   \
    if(FLAG)j=-j;   \
}
#define lson i<<1,a,m
#define rson i<<1|1,m,b
#define MaxN 205

struct Node{
    int cover;//覆盖次数
    double s;//被覆盖的总长度
}T[MaxN<<2];
int n,cntx,cnty;
double x[MaxN],y[MaxN];
int newx[MaxN],newy[MaxN];
double hashx[MaxN],hashy[MaxN];
void UpDate(int i,int a,int b,int c,int d,int val){//(1,1,n,c,d,val)
    int m=(a+b)>>1;
    if(a==c&&b==d) T[i].cover+=val;
    else if(d<=m) UpDate(lson,c,d,val);
    else if(c>=m) UpDate(rson,c,d,val);
    else{
        UpDate(lson,c,m,val);
        UpDate(rson,m,d,val);
    }
    if(T[i].cover>0) {
        T[i].s=hashx[b]-hashx[a];
    }
    else if(a+1<b) {
        T[i].s=T[i<<1].s+T[i<<1|1].s;
    }
    else {
        T[i].s=0;
    }
}
struct nod{
    int x1,x2,y,f;//f=1为底边 f=-1为顶边
}u[MaxN];//u为横边
bool cmp(nod n1,nod n2){return n1.y<n2.y;}
struct no{
    double num;
    int id;
}lx[MaxN],ly[MaxN];
bool cmp1(no n1,no n2){return n1.num<n2.num;}

void readData(){
    for(int i=1;i<=n;i++){
        cind(x[i<<1]);cind(y[i<<1]);cind(x[i<<1|1]);cind(y[i<<1|1]);
        lx[i<<1].num=x[i<<1]; lx[i<<1|1].num=x[i<<1|1];
        ly[i<<1].num=y[i<<1]; ly[i<<1|1].num=y[i<<1|1];
        lx[i<<1].id=ly[i<<1].id=i<<1;
        lx[i<<1|1].id=ly[i<<1|1].id=i<<1|1;
    }
}

void LiSan(){
    sort(lx+2,lx+((n+1)<<1),cmp1);
    sort(ly+2,ly+((n+1)<<1),cmp1);
    lx[1].num=ly[1].num=-99999999;
    cntx=cnty=0;
    for(int i=2;i<=(n<<1|1);i++){
        if(lx[i].num!=lx[i-1].num)cntx++;
        if(ly[i].num!=ly[i-1].num)cnty++;
        newx[lx[i].id]=cntx;
        newy[ly[i].id]=cnty;
        hashx[cntx]=lx[i].num;
        hashy[cnty]=ly[i].num;
    }
    for(int i=1;i<=n;i++){
        u[i<<1].x1 = u[i<<1|1].x1 = newx[i<<1];
        u[i<<1].x2 = u[i<<1|1].x2 = newx[i<<1|1];
        u[i<<1].y=newy[i<<1];    u[i<<1|1].y=newy[i<<1|1];
        u[i<<1].f=1;    u[i<<1|1].f=-1;
    }
    sort(u+2,u+((n+1)<<1),cmp);
}
int main()
{
    int Case=0;
    while(cin>>n&&n){
        Case++;
        readData();
        LiSan();
        memset(T,0,sizeof(T));
        double sum=0;
        for(int i=2;i<=(n<<1|1);i++){
            UpDate(1,1,cntx,u[i].x1,u[i].x2,u[i].f);
            if(i<(n<<1|1))sum+=T[1].s*(hashy[u[i+1].y]-hashy[u[i].y]);
        }

        cout<<"Test case #"<<Case<<endl;
        cout<<"Total explored area: "<<fixed<<setprecision(2)<<sum<<endl<<endl;
    }
    return 0;
}
View Code

 

poj 1177 矩形周长并      离散化+排序+扫描线

每处理一条横边,记录T[1]的被覆盖长度的增量,即为横着的轮廓
num记录区间内的被覆盖的段数,T[1].num*y方向的增量*2即为竖着的轮廓

int NUM,FLAG;   //输入优化
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define cini(j) {   \
    j=FLAG=0; NUM=getchar();   \
    while(!DIG(NUM)&&NUM!='-')NUM=getchar();   \
    if(NUM=='-'){FLAG=1;NUM=getchar();}   \
    j=NUM-'0';NUM=getchar();   \
    while(DIG(NUM)){j=10*j+(NUM-'0');NUM=getchar();}   \
    if(FLAG)j=-j;   \
}
#define lson i<<1,a,m
#define rson i<<1|1,m,b
#define MaxN 10005
struct Node{
    int cover,s;//cover覆盖次数 s区间被覆盖长度
    int num;
    bool left,right;
}T[MaxN<<2];
int n,cntx,cnty;
int x[MaxN],y[MaxN];
int newx[MaxN],newy[MaxN];
int hashx[MaxN],hashy[MaxN];
void UpDate(int i,int a,int b,int c,int d,int val){//(1,1,n,c,d,val)
    int m=(a+b)>>1;
    if(a==c&&b==d) T[i].cover+=val;
    else if(d<=m) UpDate(lson,c,d,val);
    else if(c>=m) UpDate(rson,c,d,val);
    else{
        UpDate(lson,c,m,val);
        UpDate(rson,m,d,val);
    }
    if(T[i].cover>0) {
        T[i].s=hashx[b]-hashx[a];
        T[i].left=T[i].right=true;
        T[i].num=1;
    }
    else if(a+1<b) {
        T[i].s=T[i<<1].s+T[i<<1|1].s;
        T[i].left=T[i<<1].left;
        T[i].right=T[i<<1|1].right;
        T[i].num=T[i<<1].num+T[i<<1|1].num;
        if(T[i<<1].right&&T[i<<1|1].left)T[i].num--;
    }
    else {
        T[i].s=0;
        T[i].left=T[i].right=false;
        T[i].num=0;
    }
}
struct nod{
    int x1,x2,y,f;//f=1为底边 f=-1为顶边
}u[MaxN];//u为横边
bool cmp(nod n1,nod n2){return n1.y<n2.y;}

struct no{
    int num,id;
}lx[MaxN],ly[MaxN];
bool cmp1(no n1,no n2){return n1.num<n2.num;}

void readData(){
    cini(n);
    for(int i=1;i<=n;i++){
        cini(x[i<<1]);cini(y[i<<1]);cini(x[i<<1|1]);cini(y[i<<1|1]);
        lx[i<<1].num=x[i<<1]; lx[i<<1|1].num=x[i<<1|1];
        ly[i<<1].num=y[i<<1]; ly[i<<1|1].num=y[i<<1|1];
        lx[i<<1].id=ly[i<<1].id=i<<1;
        lx[i<<1|1].id=ly[i<<1|1].id=i<<1|1;
    }
}

void LiSan(){
    sort(lx+2,lx+((n+1)<<1),cmp1);
    sort(ly+2,ly+((n+1)<<1),cmp1);
    lx[1].num=ly[1].num=-99999999;
    for(int i=2;i<=(n<<1|1);i++){
        if(lx[i].num!=lx[i-1].num)cntx++;
        if(ly[i].num!=ly[i-1].num)cnty++;
        newx[lx[i].id]=cntx;
        newy[ly[i].id]=cnty;
        hashx[cntx]=lx[i].num;
        hashy[cnty]=ly[i].num;
    }
    for(int i=1;i<=n;i++){
        u[i<<1].x1 = u[i<<1|1].x1 = newx[i<<1];
        u[i<<1].x2 = u[i<<1|1].x2 = newx[i<<1|1];
        u[i<<1].y=newy[i<<1];    u[i<<1|1].y=newy[i<<1|1];
        u[i<<1].f=1;    u[i<<1|1].f=-1;
    }
    sort(u+2,u+((n+1)<<1),cmp);
}
void solve(){
    int t=0,t1,t2;
    for(int i=2;i<=(n<<1|1);i++){
        t1=T[1].s;
        UpDate(1,1,cntx,u[i].x1,u[i].x2,u[i].f);
        t2=T[1].s;
        t+=t1>t2?t1-t2:t2-t1;
        if(i<(n<<1|1))t+=T[1].num*(hashy[u[i+1].y]-hashy[u[i].y])*2;
    }
    cout<<t<<endl;
}
int main()
{
    readData();
    LiSan();
    solve();
    return 0;
}
View Code

 

poj 1823     c=1 将i开始的m个元素变为1          c=2 将i开始的m个元素变为0          c=3 输出最长的连续0的个数

每个结点存储:         l:区间左边连续0的个数         r:区间右边连续0的个数         ma:区间内最大连续0的个数

int NUM,FLAG;   //ÊäÈëÓÅ»¯
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define cini(j) {   \
    j=FLAG=0; NUM=getchar();   \
    while(!DIG(NUM)&&NUM!='-')NUM=getchar();   \
    if(NUM=='-'){FLAG=1;NUM=getchar();}   \
    j=NUM-'0';NUM=getchar();   \
    while(DIG(NUM)){j=10*j+(NUM-'0');NUM=getchar();}   \
    if(FLAG)j=-j;   \
}
#define lson i<<1,a,m
#define rson i<<1|1,m+1,b
#define MaxN 16005
int n;
struct Node{
    int l,r,ma,s;
    bool lazy;
}T[MaxN<<2];
void MakeTree(int i,int a,int b){//(1,a,b)
    T[i].l=T[i].r=T[i].ma=b-a+1;
    T[i].s=T[i].lazy=0;
    if(a<b){
        int m=(a+b)>>1;
        MakeTree(lson);
        MakeTree(rson);
    }
    else{}
}
void PushDown(int i,int a,int b){
    int m=(a+b)>>1;
    T[i].lazy=0;
    if(a<b){
        T[i<<1].lazy=T[i<<1|1].lazy=1;
        T[i<<1].s=T[i].s; T[i<<1|1].s=T[i].s;
        T[i<<1].l=T[i<<1].r=T[i<<1].ma=(m-a+1)*(1-T[i<<1].s);
        T[i<<1|1].l=T[i<<1|1].r=T[i<<1|1].ma=(b-m)*(1-T[i<<1|1].s);
    }
}
int Max(int a,int b,int c){
    int t=a>b?a:b;
    t=t>c?t:c;
    return t;
}
void PushUp(int i,int a,int b){
    int m=(a+b)>>1;
    T[i].ma=Max(T[i<<1].ma,T[i<<1|1].ma,T[i<<1].r+T[i<<1|1].l);
    T[i].l=T[i<<1].l;   T[i].r=T[i<<1|1].r;
    if(T[i<<1].l==(m-a+1))T[i].l+=T[i<<1|1].l;
    if(T[i<<1|1].r==(b-m))T[i].r+=T[i<<1].r;
}
void UpDate(int i,int a,int b,int c,int d,int val){//(1,1,n,c,d,val)
                        //cout<<i<<' '<<a<<' '<<b<<' '<<c<<' '<<d<<' '<<val<<' '<<endl;
    if(a==c&&b==d){
        T[i].s=val;T[i].lazy=1;
        T[i].l=T[i].r=T[i].ma=(b-a+1)*(1-val);
        return;
    }
    if(T[i].lazy)PushDown(i,a,b);
    int m=(a+b)>>1;
    if(d<=m){
        UpDate(lson,c,d,val);
    }
    else if(c>=m+1){
        UpDate(rson,c,d,val);
    }
    else{
        UpDate(lson,c,m,val);
        UpDate(rson,m+1,d,val);
    }
    if(a<b)PushUp(i,a,b);
}

int main() {
    int p;
    cini(n);cini(p);
    MakeTree(1,1,n);
    int c,i,m;
    while(p--){
        cini(c);
        if(c==1){
            cini(i);cini(m);
            UpDate(1,1,n,i,i+m-1,1);
        }
        else if(c==2){
            cini(i);cini(m);
            UpDate(1,1,n,i,i+m-1,0);
        }
        else printf("%d\n",T[1].ma); 
    }
    return 0;
}
View Code

 

poj 2155     二维线段树      A[n][n]的矩阵 元素初始化全为0 给以下两种指令:

C a b c d表示从左上角(a,b)到右下角(c,d)的矩形内元素取反
Q a b 表示询问A[a][b]的值

#define Left(i) (i<<1)
#define Right(i) (i<<1|1)
#define MaxN 1010
#define Mx 2400
#define My 2400

struct SubNode{
    int a,b;
    int mid(){return (a+b)/2;}
    int ad;
};
struct Node{
    int a,b;
    int mid(){return (a+b)/2;}
    SubNode t[My];
}T[Mx];

void MakeT(int i,int j,int a,int b){
    T[i].t[j].a=a; T[i].t[j].b=b; T[i].t[j].ad=0;
    if(a<b){
        MakeT(i,Left(j),a, T[i].t[j].mid() );
        MakeT(i,Right(j), T[i].t[j].mid()+1 ,b);
    }
}
void MakeTree(int i,int a,int b,int c,int d){//(1,  a,b  ,c,d)
    T[i].a=a; T[i].b=b;
    MakeT(i,1,c,d);
    if(a<b){
        MakeTree(Left(i),a, T[i].mid() ,c,d);
        MakeTree(Right(i), T[i].mid()+1,b,c,d);
    }
}

int flag;
void query(int i,int j,int b){
    if(T[i].t[j].ad) flag^=1;
    if(b==T[i].t[j].a&&T[i].t[j].b==b)return;
    if(b<T[i].t[j].mid()+1)     query(i,Left(j),b);
    else if(b>T[i].t[j].mid())  query(i,Right(j),b);
}
void Query(int i,int a,int b){//(1, a,b )
    query(i,1,b);
    if(a==T[i].a&&T[i].b==a)return;
    if(a<T[i].mid()+1)      Query(Left(i),a,b);
    else if(a>T[i].mid())   Query(Right(i),a,b);
}

void Update(int i,int j,int a,int b){
    if(a==T[i].t[j].a&&T[i].t[j].b==b) T[i].t[j].ad^=1;
    else if(b<T[i].t[j].mid()+1)    Update(i,Left(j),a,b);
    else if(a>T[i].t[j].mid())      Update(i,Right(j),a,b);
    else{
        Update(i,Left(j),a,T[i].t[j].mid());
        Update(i,Right(j),T[i].t[j].mid()+1,b);
    }
}
void UpDate(int i,int a,int b,int c,int d){//(1, a,b,  c,d,  ad)在树i中的abcd区间取反
    if(a==T[i].a&&T[i].b==b)    Update(i,1,c,d);
    else if(b<T[i].mid()+1)     UpDate(Left(i),a,b,c,d);
    else if(a>T[i].mid())       UpDate(Right(i),a,b,c,d);
    else{
        UpDate(Left(i),a,T[i].mid(),c,d);
        UpDate(Right(i),T[i].mid()+1,b,c,d);
    }
}

int NUM,FLAG;   //输入优化
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define cini(j) {   \
    j=FLAG=0; NUM=getchar();   \
    while(!DIG(NUM)&&NUM!='-')NUM=getchar();   \
    if(NUM=='-'){FLAG=1;NUM=getchar();}   \
    j=NUM-'0';NUM=getchar();   \
    while(DIG(NUM)){j=10*j+(NUM-'0');NUM=getchar();}   \
    if(FLAG)j=-j;   \
}

int main()
{
    int xx,n,tt,  a,b,c,d;
    char ch;
    cin>>xx;
    while(xx--){
        cin>>n>>tt;
        MakeTree(1,1,n,1,n);
        while(tt--){
            cin>>ch;
            if(ch=='C'){
                cini(a);cini(c);cini(b);cini(d);
                //cin>>a>>c>>b>>d;
                UpDate(1,a,b,c,d);
            }
            else{
                cini(a);cini(b);
                //cin>>a>>b;
                flag=0;
                Query(1,a,b);
                cout<<flag<<endl;
            }
        }
        cout<<endl;
    }
    return 0;
}
View Code

 

poj 2299 求逆序数 存储区间内已有的元素个数,每更新一个新数字i,先累加区间 i+1,maxn然后包含i的区间+1

#define Left(i) (i<<1)
#define Right(i) (i<<1|1)
#define Mid(i) ((T[i].a+T[i].b)>>1)
#define MaxN 1000010
#define MAXN 2000100
long long cnt;
int arr[MaxN];
struct Node{
    int a,b;  //区间
    long long sum,ad; //区间总和  单个元素增量
}T[MAXN];
void MakeTree(int a,int b,int i){//(1,MAXN,1)
    T[i].a=a; T[i].b=b; T[i].sum=T[i].ad=0;
    if(a<b){
        MakeTree(a,Mid(i),Left(i));
        MakeTree(Mid(i)+1,b,Right(i));
    }
}
void Fen(int i){
    if(T[i].a==T[i].b){
        T[i].sum+=T[i].ad;
        T[i].ad=0;
    }
    else{
        T[Left(i)].ad+=T[i].ad;
        T[Right(i)].ad+=T[i].ad;
        T[i].sum+=(T[i].b-T[i].a+1)*T[i].ad;
        T[i].ad=0;
    }
}
long long Query(int i,int c,int d){//区间cd的sum值之和
    Fen(i);
    long long temp=0;
    if(c==T[i].a&&T[i].b==d) {
        temp += T[i].sum;
    }
    else if(d<Mid(i)+1) {   //cd仅在左子树
        temp += Query(Left(i),c,d);
    }
    else if(c>Mid(i)){  //cd仅在右子树
        temp += Query(Right(i),c,d);
    }
    else {  //cd跨越左右子树
        temp += Query(Left(i),c,Mid(i));
        temp += Query(Right(i),Mid(i)+1,d);
    }
    return temp;
}
long long Insert(int i,int c,int d,int odd){//在树i中的cd区间增odd
    long long temp=0;
    if(c==T[i].a&&T[i].b==d){
        T[i].ad+=odd; return (d-c+1)*odd;
    }
    if(d<Mid(i)+1){  //cd仅在左子树
        temp=Insert(Left(i),c,d,odd);
    }
    else if(c>Mid(i)){   //cd仅在右子树
        temp=Insert(Right(i),c,d,odd);
    }
    else{       //cd跨越左右子树
        temp+=Insert(Left(i),c,Mid(i),odd);
        temp+=Insert(Right(i),Mid(i)+1,d,odd);
    }
    T[i].sum+=temp;
    return temp;
}

int n,j;
void solve(){
    for(int i=1;i<=n;i++){
        if(arr[i]!=j)
            cnt+=Query(1,arr[i]+1,j);
        Insert(1,arr[i],arr[i],1);
    }
    cout<<cnt<<endl;
}

int NUM,FLAG;
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define cini(j) {   \
    j=FLAG=0; NUM=getchar();   \
    while(!DIG(NUM)&&NUM!='-')NUM=getchar();   \
    if(NUM=='-'){FLAG=1;NUM=getchar();}   \
    j=NUM-'0';NUM=getchar();   \
    while(DIG(NUM)){j=10*j+(NUM-'0');NUM=getchar();}   \
    if(FLAG)j=-j;   \
}

struct nod{
    int num,id;
}B[MaxN];
bool cmp(nod n1,nod n2){return n1.num<n2.num;}

void readData(){
    B[0].num=-1;B[0].id=0;
    cnt=0;
    for(int i=1;i<=n;i++) {cini(B[i].num);B[i].id=i;}
    sort(B+1,B+n+1,cmp);
    j=0;
    for(int i=1;i<=n;i++){
        if(B[i].num!=B[i-1].num)j++;
        arr[B[i].id]=j;
    }
}
int main()
{
    while(cin>>n&&n){
        readData();
        MakeTree(1,j,1);
        solve();
    }
    return 0;
}
View Code

 

poj 2528 在墙上贴海报,可以互相覆盖,问最后可以看见几张海报

普通离散化的缺陷:
例一:  1-10   1-4   5-10
例二:  1-10   1-4   6-10
离散化后都变成了[1,4]  [1,2]  [3,4]
线段2覆盖了[1,2], 线段3覆盖了[3,4], 那么线段1是否被完全覆盖掉了呢?
例一是完全被覆盖掉了,  而例二没有被覆盖

解决办法:
25、26本身相邻,离散为1、2
25、30本身不相邻,中间加一个数,离散为1、3

#define lson i<<1,a,m
#define rson i<<1|1,m+1,b
#define MaxN 40005
struct Node{
    int color;
    bool lazy;
}T[MaxN<<2];
void MakeTree(int i,int a,int b){//(1,a,b)
    T[i].color=T[i].lazy=0;
    if(a<b){
        int m=(a+b)>>1;
        MakeTree(lson);
        MakeTree(rson);
    }
    else{}
}
void PushDown(int i){
    T[i<<1].lazy=T[i<<1|1].lazy=1;
    T[i].lazy=0;
    T[i<<1].color=T[i<<1|1].color=T[i].color;
}
void UpDate(int i,int a,int b,int c,int d,int val){//(1,1,n,c,d,val)
    if(a==c&&b==d){
        T[i].color=val;T[i].lazy=1;return;
    }
    int m=(a+b)>>1;
    if(T[i].lazy&&a<b)PushDown(i);
    if(d<=m){
        UpDate(lson,c,d,val);
    }
    else if(c>=m+1){
        UpDate(rson,c,d,val);
    }
    else{
        UpDate(lson,c,m,val);
        UpDate(rson,m+1,d,val);
    }
}


int cnt;
bool bo[10005];
void Query(int i,int a,int b,int c,int d){
    int m=(a+b)>>1;
    if(T[i].lazy){
        int t=T[i].color;
        if(t&&!bo[t]){
            bo[t]=1;
            cnt++;
        }
        return;
    }
    if(a==b)return;
    Query(lson,c,m);
    Query(rson,m+1,d);
}



struct No{
    int num,id;
}no[20005];
bool cmp(No n1,No n2){
    return n1.num<n2.num;
}
int nn[20005];
int n,abc;
void LiSan(){//ÀëÉ¢»¯
    cini(n);
    memset(no,0,sizeof(no));
    int i;
    for(i=1;i<=n;i++){
        cini(no[2*i].num);  no[2*i].id=2*i;
        cini(no[2*i+1].num);no[2*i+1].id=2*i+1;
    }
    sort(no+2,no+2*i,cmp);
    no[1].num=-1; abc=0;
    for(int i=2;i<=2*n+1;i++){
        if(no[i-1].num!=no[i].num){
            if(no[i-1].num+1==no[i].num)abc++;
            else abc+=2;
        }
        nn[no[i].id]=abc;
    }
}
int main()
{
    int c; cini(c);
    while(c--){
        LiSan();
        MakeTree(1,1,abc);
        memset(bo,0,sizeof(bo));
        int col=0;
        for(int i=1;i<=n;i++){
            col++;
            UpDate(1,1,abc,nn[2*i],nn[2*i+1],col);
        }
        cnt=0;
        Query(1,1,abc,1,abc);
        cout<<cnt<<endl;
    }
    return 0;
}
View Code

 

poj 2828 人们一个一个的来排队并插队,按人到来的顺序给出每个人插队的位置(插在第几个人后面),并告知每个人的id号,输出最终队伍的情况。

从最后来的一个人开始向来的更早的人遍历,这样pos(插在第几个人后面)的意义就变成了,前面有多少个空位。线段树上每个节点中存储的是当前时刻,该区间有多少空位。

struct Node{
    int num;
}T[MaxN<<2];
void MakeTree(int i,int a,int b){//(1,a,b)
    T[i].num=b-a+1;
    if(a<b){
        int m=(a+b)>>1;
        MakeTree(lson);
        MakeTree(rson);
    }
}
int x[MaxN],y[MaxN],z[MaxN],val;
void UpDate(int i,int a,int b,int c){//寻找第c个空位
    T[i].num--;
    int m=(a+b)>>1;
    if(a==b)    z[a]=val;
    else if(c>T[i<<1].num)UpDate(rson,c-T[i<<1].num);
    else UpDate(lson,c);
}

int main()
{
    int n;
    while(cin>>n){
        MakeTree(1,1,n);
        for(int i=1;i<=n;i++){
            cini(x[i]);cini(y[i]);
        }
        for(int i=n;i>=1;i--){
            val=y[i];
            UpDate(1,1,n,x[i]+1);
        }
        for(int i=1;i<=n;i++)
            printf("%d ",z[i]);
        cout<<endl;
    }
    return 0;
}
View Code

 

poj 2886 

N 个小孩围成一圈,顺时针编号为 1 到 N。每个小孩手中有一个卡片,上面有一个非 0 的数字,游戏从第 K 个小孩开始,他告诉其他小孩他卡片上的数字并离开这个圈,他卡片上的数字 A 表明了下一个离开的小孩,如果 A 是大于 0 的,则下个离开的是左手边第 A 个,如果是小于 0 的,则是右手边的第 -A 个小孩。游戏将直到所有小孩都离开,在游戏中,第 p 个离开的小孩将得到 F(p) 个糖果,F(p) 是 p 的约数的个数,问谁将得到最多的糖果。输出最幸运的小孩的名字和他可以得到的糖果。

打表求反素数,根据反素数求第几个离开得到糖果最多

线段树存储区间内剩下的人数,
若k>lson.sum 则到右子树中找第k-lson.sum个人
否则在左子树中找第k个人

#define lson i<<1,a,m
#define rson i<<1|1,m+1,b
#define MaxN 500010

struct Node{
    int sum;
}T[MaxN<<2];

int n,k;
inline void MakeTree(int i,int a,int b){//(1,a,b)
    T[i].sum=b-a+1;
    if(a<b){
        int m=(a+b)>>1;
        MakeTree(lson);
        MakeTree(rson);
    }
}
inline int UpDate(int i,int a,int b,int t){//(1,1,n,c,d,val)
    T[i].sum--;
    if(a==b) return a;
    int m=(a+b)>>1;
    if(t>T[i<<1].sum)return UpDate(rson,t-T[i<<1].sum);
    else return UpDate(lson,t);
}
/*
int Query(int i,int a,int b,int c,int d){
    if(a==c&&b==d) {
        return T[i].sum;
    }
    int temp=0,m=(a+b)>>1;
    if(d<=m) {
        temp=Query(lson,c,d);
    }
    else if(c>=m+1){
        temp=Query(rson,c,d);
    }
    else {
        temp+=Query(lson,c,m);
        temp+=Query(rson,m+1,d);
    }
    return temp;
}*/
/*int db[MaxN],p[MaxN];//db[i]:i的因子数  p[i]: db[1]~db[i]最大者的下标
void dabiao(){
    for(int i=1;i<=MaxN;i++)
        for(int j=i;j<=MaxN;j+=i)
            db[j]++;
    int pos=0,val=0;
    for(int i=1;i<=MaxN;i++){
        if(db[i]>val){val=db[i];pos=i;}
        p[i]=pos;
    }
}*/

const int antiprime[] = {1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,
                25200,27720,45360,50400,55440,83160,110880,166320,221760,277200,332640,498960,554400,665280};
const int factorNum[] = {1,2,3,4,6,8,9,10,12,16,18,20,24,30,32,36,40,48,60,64,72,
                80,84,90,96,100,108,120,128,144,160,168,180,192,200,216,224};


char name[MaxN][11];
int card[MaxN];
void readData(){
    //scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        //scanf("%s",name[i]);
        //cini(card[i]);
        scanf("%s%d",name[i],&card[i]);
    }
}
void solve(){              //cout<<"A"<<endl;
    int p=0;
    while(antiprime[p++]<=n);
    p-=2;
    int u=antiprime[p],pos,mod=n,t=0;
    for(int i=1;i<=u;i++){
        if(t>0) k=(k+t-2)%mod+1;
        else k = ((k+t-1)%mod+mod)%mod+1;
        pos=UpDate(1,1,n,k);
        mod--;
        t =card[pos];
        //if(mod==0)break;

    }
    printf("%s %d\n",name[pos],factorNum[p]);
  /*  while(times--){
        //int t=(Lnum+k-1)%T[1].sum+1;
                                                                    //cout<<"k="<<k<<' '<<T[1].sum<<endl;;
                                                                    //if(T[1].sum<=1)break;
        if(k>0)k=(k-1)%T[1].sum+1;
        else {
            k=(k+1)%T[1].sum-1;                                                //cout<<k<<endl;
            k=k+T[1].sum+1;
        }
        int t=Lnum+k;
        if(t>T[1].sum)t-=T[1].sum;
        pos=UpDate(1,1,n,t);
        Lnum=Query(1,1,n,1,pos);
        k=card[pos];                                                //cout<<name[pos]<<' '<<t<<' '<<Lnum<<endl;
    }   */                                                                    //cout<<"                   "<<c<<"    ";
    //cout<<name[pos]<<' '<<db[u]<<endl;

}
int main()
{
    //dabiao();
    while(scanf("%d%d",&n,&k)!=EOF){
        readData();
        MakeTree(1,1,n);
        solve();
    }
    return 0;
}
View Code

 

poj 3667 

输入a, b, c
a==1, 输出最左边的连续b个0的起始位置, 并将b个0置为1
a==2, b开始的连续c个元素置为0

分析:
记录 左边连续0的个数,右边连续0的个数,最大0的个数

#define lson i<<1,a,m
#define rson i<<1|1,m+1,b
#define MaxN 50005
int n;
struct Node{
    int l,r,ma;//左边空房间数 右边空房间数 最大空房间数
    bool lazy,f;
}T[MaxN<<2];
void MakeTree(int i,int a,int b){//(1,a,b)
    T[i].l=T[i].r=T[i].ma=b-a+1;
    T[i].f=T[i].lazy=0;
    if(a<b){
        int m=(a+b)>>1;
        MakeTree(lson);
        MakeTree(rson);
    }
}
inline int Max(int a,int b){return a>b?a:b;}
void PushDown(int i,int a,int b){
    int m=(a+b)>>1;
    T[i].lazy=0;
    if(a<b){
        T[i<<1].lazy=T[i<<1|1].lazy=1;
        if(T[i].f==0){
            T[i<<1].f=T[i<<1|1].f=0;
            T[i<<1].l=T[i<<1].r=T[i<<1].ma=m-a+1;
            T[i<<1|1].l=T[i<<1|1].r=T[i<<1|1].ma=b-m;
        }
        else{
            T[i<<1].f=T[i<<1|1].f=1;
            T[i<<1].l=T[i<<1].r=T[i<<1].ma=0;
            T[i<<1|1].l=T[i<<1|1].r=T[i<<1|1].ma=0;
        }
    }
}
void PushUp(int i,int a,int b){
    int m=(a+b)>>1;
    T[i].l=T[i<<1].l;
    if(T[i<<1].l==m-a+1)T[i].l+=T[i<<1|1].l;
    T[i].r=T[i<<1|1].r;
    if(T[i<<1|1].r==b-m)T[i].r+=T[i<<1].r;
    T[i].ma=Max(T[i<<1].ma,T[i<<1|1].ma);
    T[i].ma=Max(T[i].ma,T[i<<1].r+T[i<<1|1].l);
}
void Delete(int i,int a,int b,int c,int d){//删除
    if(a==c&&b==d){
        T[i].lazy=1;    T[i].f=0;
        T[i].l=T[i].r=T[i].ma=b-a+1;
        return;
    }
    if(T[i].lazy)PushDown(i,a,b);
    int m=(a+b)>>1;
    if(d<=m) Delete(lson,c,d);
    else if(c>=m+1) Delete(rson,c,d);
    else{
        Delete(lson,c,m);
        Delete(rson,m+1,d);
    }
    if(a<b)PushUp(i,a,b);
}
int Insert(int i,int a,int b,int c,bool v){//v为真 则在最左边找连续的c个空房间  否则在最右边找
    int m=(a+b)>>1,ans=0;
    if(b-a+1==c){
        T[i].lazy=1;T[i].f=1;
        T[i].l=T[i].r=T[i].ma=0;
        return a;
    }
    if(T[i].lazy)PushDown(i,a,b);
    if(v){//先左 再中 后右
        if(T[i<<1].ma>=c) ans= Insert(lson,c,true);
        else if(T[i<<1].r&&T[i<<1|1].l&&T[i<<1].r+T[i<<1|1].l>=c){
            int temp=T[i<<1].r;
            ans=Insert(lson,temp,false);
            Insert(rson,c-temp,true);//
        }
        else if(T[i<<1|1].ma>=c) ans=Insert(rson,c,true);
    }
    else{//先右 再中 后左
        if(T[i<<1|1].ma>=c) ans= Insert(rson,c,false);
        else if(T[i<<1].r&&T[i<<1|1].l&&T[i<<1].r+T[i<<1|1].l>=c){
            int temp=T[i<<1|1].l;
            ans=Insert(lson,c-temp,false);
            Insert(rson,temp,true);
        }
        else if(T[i<<1].ma>=c) ans=Insert(lson,c,false);
    }
    if(a<b)PushUp(i,a,b);
    return ans;
}
int main()
{
    int p;
    cini(n);cini(p);
    MakeTree(1,1,n);
    int c,i,m;
    while(p--){
        cini(c);
        if(c==1){
            cini(i);
            cout<<Insert(1,1,n,i,true)<<endl;
        }
        else if(c==2){
            cini(i);cini(m);
            Delete(1,1,n,i,i+m-1);
        }
    }
    return 0;
}
View Code

 

posted @ 2013-06-22 15:52  心向往之  阅读(237)  评论(0编辑  收藏  举报