zoukankan      html  css  js  c++  java
  • 各种骚操作线段树

             线段树是世界上最美的数据结构(主要记录一些有意义的线段树.....特别是骚操作

    1.uestc1425 Another LCIS  http://acm.uestc.edu.cn/#/problem/show/360

    题意:两种操作 对于一段区间的数加上c 查询最长连续上升序列

    题解:彻底弄清楚区间更新lazy的含义 就是切水题 直接区间更新然后区间合并用点小技巧即可

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #define N 100005
    using namespace std;
    typedef struct node{
        int l;int r;int l1;int len1;int r1;int len2;
        int len;int flag;
    }node;
    node d[N<<2];
    int a[N];
    void up(int root){
        d[root].l1=d[root<<1].l1;d[root].r1=d[root<<1|1].r1;
        if(d[root<<1].r1<d[root<<1|1].l1){
            d[root].len=max(d[root<<1].len,max(d[root<<1].len2+d[root<<1|1].len1,d[root<<1|1].len));
            if(d[root<<1].len1==(d[root<<1].r-d[root<<1].l+1))
                 d[root].len1=d[root<<1].len1+d[root<<1|1].len1;
            else d[root].len1=d[root<<1].len1;
            if(d[root<<1|1].len2==(d[root<<1|1].r-d[root<<1|1].l+1))
                 d[root].len2=d[root<<1].len2+d[root<<1|1].len2;
            else d[root].len2=d[root<<1|1].len2;
        }
        else{
            d[root].len=max(d[root<<1].len,d[root<<1|1].len);
            d[root].len1=d[root<<1].len1;d[root].len2=d[root<<1|1].len2;
        }
    }
    void push(int root){
        d[root<<1].l1+=d[root].flag;d[root<<1].r1+=d[root].flag;
        d[root<<1|1].l1+=d[root].flag;d[root<<1|1].r1+=d[root].flag;
        d[root<<1].flag+=d[root].flag;d[root<<1|1].flag+=d[root].flag;
        d[root].flag=0;
    }
    void built(int root,int l,int r){
        if(l==r){
            d[root].l=l;d[root].r=r;d[root].l1=a[l];d[root].r1=a[l];d[root].len1=1;d[root].len2=1;d[root].len=1;
            d[root].flag=0;
            return ;
        }
        int mid=(l+r)>>1;
        built(root<<1,l,mid);
        built(root<<1|1,mid+1,r);
        d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r;d[root].flag=0;up(root);
    }
    void update(int root,int l,int r,int e){
        if(l<=d[root].l&&d[root].r<=r){
            d[root].flag+=e;
            d[root].l1+=e;d[root].r1+=e;
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) update(root<<1,l,r,e);
        if(r>mid) update(root<<1|1,l,r,e);
        up(root);
    }
    int ans;int tt;node ttt;
    void genxin(int root){
            ttt.len=max(ttt.len,max(ttt.len2+d[root].len1,d[root].len));
            if(ttt.len1==(ttt.r-ttt.l+1))
                 ttt.len1=ttt.len1+d[root].len1;
            else ttt.len1=ttt.len1;
            if(d[root].len2==(d[root].r-d[root].l+1))
                 ttt.len2=ttt.len2+d[root].len2;
            else ttt.len2=d[root].len2;
            ttt.r1=d[root].r1;
    }
    void querty(int root,int l,int r){
        if(l<=d[root].l&&d[root].r<=r){
            if(tt==0) {ans=d[root].len;ttt=d[root];}
            else{
              //  cout<<ttt.r1<<" "<<d[root].l1<<endl;
                if(ttt.r1<d[root].l1){
                    genxin(root);
                    ans=max(ans,ttt.len);
                }
                else{
                    ans=max(ans,d[root].len);ttt=d[root];
                }
            }tt=1;
      //  cout<<d[root].l<<" "<<d[root].r<<" "<<ans<<endl;
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) querty(root<<1,l,r);
        if(r>mid) querty(root<<1|1,l,r);
        up(root);
    }
    int main(){
        int Case=0;int T;
      //  freopen("1.txt","r",stdin);
        scanf("%d",&T);
        char str[10];
        while(T--){
            int n,m;scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            built(1,1,n);
            printf("Case #%d:
    ",++Case);
            for(int i=1;i<=m;i++){
                scanf("%s",str);
                int t1,t2,t3;
                if(str[0]=='a'){
                    scanf("%d%d%d",&t1,&t2,&t3);
                    update(1,t1,t2,t3);
                }
                else if(str[0]=='q'){
                    scanf("%d%d",&t1,&t2);
                    tt=0;
                    querty(1,t1,t2);
                    printf("%d
    ",ans);
                }
            }
        }
        return 0;
    }
    

     2.POJ 2991http://poj.org/problem?id=2991

       题意:有n根棍子 每根棍子直接用一个节点相连 可旋转  有m种操作 即旋转s和s+1直接的节点 使节点成a角度 对于每次变化输出最后一个点的位置

       题解:由向量旋转定理 对于增加的角度b 有x1=x0*cosb-y0*sinb;y1=sinb*x0+cosb*y0;然后线段树区间维护即可

    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #include <cstdio>
    #include <cmath>
    #define N 20005
    #define pi (acos(-1.0))
    using namespace std;
    typedef struct node{
        int l;int r;double t1,t2;
        int t;
        int flag;
    }node;
    node d[N<<2];
    int a[N];
    void upsh(int root){
        d[root].t1=d[root<<1].t1+d[root<<1|1].t1;
        d[root].t2=d[root<<1].t2+d[root<<1|1].t2;
    }
    void built(int root,int l,int r){
        if(l==r){
            d[root].l=l;d[root].r=r;d[root].t1=0;d[root].t2=a[l];
            d[root].flag=0;d[root].t=0;
            return ;
        }
        int mid=(l+r)>>1;
        built(root<<1,l,mid);
        built(root<<1|1,mid+1,r);
        d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r;upsh(root);d[root].flag=0;
        d[root].t=0;
    }
    void uppush(int root){
        double tt=d[root].flag*1.0*pi/180;
        double ttt1,ttt2;
        d[root<<1].t=(d[root].flag+d[root<<1].t)%360;d[root<<1|1].t=(d[root].flag+d[root<<1|1].t)%360;
        d[root].t2=cos(tt)*ttt2+ttt1*sin(tt);
        ttt1=d[root<<1].t1;
        ttt2=d[root<<1].t2;
        d[root<<1].t1=ttt1*cos(tt)-ttt2*sin(tt);
        d[root<<1].t2=cos(tt)*ttt2+ttt1*sin(tt);
        ttt1=d[root<<1|1].t1;
        ttt2=d[root<<1|1].t2;
        d[root<<1|1].t1=ttt1*cos(tt)-ttt2*sin(tt);
        d[root<<1|1].t2=cos(tt)*ttt2+ttt1*sin(tt);
        d[root<<1].flag=(d[root<<1].flag+d[root].flag)%360;d[root<<1|1].flag=(d[root<<1|1].flag+d[root].flag)%360;
        d[root].flag=0;
    }
    void update(int root,int l,int r,int e){
        if(l<=d[root].l&&d[root].r<=r){
        d[root].flag=(d[root].flag+e)%360;d[root].t=(d[root].t+e)%360;
        double tt=e*1.0*pi/180;
        double ttt1=d[root].t1;
        double ttt2=d[root].t2;
        d[root].t1=ttt1*cos(tt)-ttt2*sin(tt);
        d[root].t2=cos(tt)*ttt2+ttt1*sin(tt);
        return ;
        }
        uppush(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) update(root<<1,l,r,e);
        if(r>mid) update(root<<1|1,l,r,e);
        upsh(root);
    }
    int ans;
    void querty(int root,int e){
        if(d[root].l==d[root].r){
          ans=d[root].t;
          return ;
        }
        uppush(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(e<=mid) querty(root<<1,e);
        else querty(root<<1|1,e);
        upsh(root);
    }
    int main(){
        int n,m;
        int Case=0;
        while(scanf("%d%d",&n,&m)==2){
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            built(1,1,n);
            int t1,t2;
            if(Case++!=0) puts("");
            for(int i=1;i<=m;i++){
                scanf("%d%d",&t1,&t2);
                querty(1,t1);
                int ans1=ans;
                querty(1,t1+1);
                int ans2=ans;
                int t=(t2-((180+ans2-ans1+360)%360))%360;
                update(1,t1+1,n,t);
                printf("%.2lf %.2lf
    ",d[1].t1,d[1].t2);
            }
        }
        return 0;
    }
    

     3.uestc1546 Bracket Sequencehttp://acm.uestc.edu.cn/#/problem/show/94

       题意:给一个括号序列,给定三种操作,一种是区间类取反 一种是区间类整体用一个括号替换 第三种查询给定区间是否匹配

       题解:令左括号'('的值为-1 右括号')'的值为1 然后查询区间和是否为0且从左到右的最大值小于等于0 否则不存在匹配

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #define N 100005
    using namespace std;
    typedef struct node{
        int l;int r;int sum;int maxx;int minn;
        int flag1;int flag2;
    }node;
    node d[N<<2];
    int a[N];
    void up(int root){
        d[root].maxx=max(d[root<<1].maxx,d[root<<1].sum+d[root<<1|1].maxx);
        d[root].minn=min(d[root<<1].minn,d[root<<1].sum+d[root<<1|1].minn);
        d[root].sum=d[root<<1].sum+d[root<<1|1].sum;
    }
    void built(int root,int l,int r){
        if(l==r){
            d[root].l=l;d[root].r=r;d[root].sum=a[l];d[root].maxx=a[l];d[root].flag1=0;d[root].flag2=0;d[root].minn=a[l];
            return ;
        }
        int mid=(l+r)>>1;
        built(root<<1,l,mid);
        built(root<<1|1,mid+1,r);
        d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r;d[root].flag1=0;d[root].flag2=0;up(root);
    }
    void push(int root){
        if(d[root].flag1!=0){
            d[root<<1].flag2=0;d[root<<1|1].flag2=0;d[root<<1].sum=(d[root<<1].r-d[root<<1].l+1)*d[root].flag1;
            d[root<<1|1].sum=(d[root<<1|1].r-d[root<<1|1].l+1)*d[root].flag1;
            d[root<<1].flag1=d[root].flag1;d[root<<1|1].flag1=d[root].flag1;
            if(d[root].flag1>0){
                d[root<<1].maxx=(d[root<<1].r-d[root<<1].l+1)*d[root].flag1;
                d[root<<1|1].maxx=(d[root<<1|1].r-d[root<<1|1].l+1)*d[root].flag1;
                d[root<<1].minn=d[root].flag1;d[root<<1|1].minn=d[root].flag1;
            }
            else{
                d[root<<1].minn=(d[root<<1].r-d[root<<1].l+1)*d[root].flag1;
                d[root<<1|1].minn=(d[root<<1|1].r-d[root<<1|1].l+1)*d[root].flag1;
                d[root<<1].maxx=d[root].flag1;d[root<<1|1].maxx=d[root].flag1;
            }
            if(d[root].flag2%2==1){
                d[root<<1].sum*=-1;d[root<<1|1].sum*=-1;
                int t=d[root<<1].maxx*-1;d[root<<1].maxx=d[root<<1].minn*-1;d[root<<1].minn=t;
                t=d[root<<1|1].maxx*-1;d[root<<1|1].maxx=d[root<<1|1].minn*-1;d[root<<1|1].minn=t;
                d[root<<1].flag2=(d[root].flag2%2+d[root<<1].flag2)%2;
                d[root<<1|1].flag2=(d[root].flag2%2+d[root<<1|1].flag2)%2;
            }
            d[root].flag1=0;d[root].flag2=0;
        }
        else{
            if(d[root].flag2%2==1){
                d[root<<1].sum*=-1;d[root<<1|1].sum*=-1;
                int t=d[root<<1].maxx*-1;d[root<<1].maxx=d[root<<1].minn*-1;d[root<<1].minn=t;
                t=d[root<<1|1].maxx*-1;d[root<<1|1].maxx=d[root<<1|1].minn*-1;d[root<<1|1].minn=t;
                d[root<<1].flag2=(d[root].flag2%2+d[root<<1].flag2)%2;
                d[root<<1|1].flag2=(d[root].flag2%2+d[root<<1|1].flag2)%2;
                d[root].flag2=0;
            }
        }
    }
    void revers(int root,int l,int r){
        if(l<=d[root].l&&d[root].r<=r){
            d[root].flag2++;
            d[root].sum=d[root].sum*-1;
            int t=d[root].maxx*-1;d[root].maxx=d[root].minn*-1;d[root].minn=t;
           // cout<<d[root].maxx<<endl;
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) revers(root<<1,l,r);
        if(r>mid) revers(root<<1|1,l,r);
        up(root);
    }
    void se(int root,int l,int r,int t){
        if(l<=d[root].l&&d[root].r<=r){
            d[root].flag1=t;d[root].flag2=0;
            d[root].sum=(d[root].r-d[root].l+1)*t;
            if(t>0){
                d[root].maxx=(d[root].r-d[root].l+1)*t;
                d[root].minn=t;
            }
            else{
                d[root].minn=(d[root].r-d[root].l+1)*t;
                d[root].maxx=t;
            }
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) se(root<<1,l,r,t);
        if(r>mid) se(root<<1|1,l,r,t);
        up(root);
    }
    int flag;int ans;int tt2;int tt1;int ttt;
    void querty(int root,int l,int r){
        if(l<=d[root].l&&d[root].r<=r){
            ans+=d[root].sum;
            if(ttt==0) {tt2=d[root].maxx;tt1+=d[root].sum;}
            else{
                tt2=max(tt2,tt1+d[root].maxx);tt1+=d[root].sum;
            }
            ttt=1;
          //  cout<<tt2<<" "<<d[root].l<<" "<<d[root].r<<endl;
            if(tt2>0) flag=1;
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) querty(root<<1,l,r);
        if(r>mid) querty(root<<1|1,l,r);
        up(root);
    }
    int main(){
        int T;scanf("%d",&T);int Case=0;
        while(T--){
            int n;char ch;scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf(" %c",&ch);
                if(ch=='(') a[i]=-1;
                else a[i]=1;
            }
            built(1,1,n);
            int m;scanf("%d",&m);
            char str[20];
          printf("Case %d:
    ",++Case);
            for(int i=1;i<=m;i++){
                scanf("%s",str);
                if(str[0]=='q'){
                    int t1,t2;scanf("%d%d",&t1,&t2);
                    t1++;t2++;
                    ans=0;flag=0;ttt=0;tt1=0;
                    querty(1,t1,t2);
                    //cout<<flag<<endl;
                    if(flag==0&&ans==0) printf("YES
    ");
                    else printf("NO
    ");
                }
                else if(str[0]=='s'){
                    int t1,t2;char ch1;
                    scanf("%d%d %c",&t1,&t2,&ch);t1++;t2++;
                    if(ch=='('){
                        se(1,t1,t2,-1);
                       }
                    else se(1,t1,t2,1);
                }
                else{
                    int t1,t2;
                    scanf("%d%d",&t1,&t2);t1++;t2++;
                    revers(1,t1,t2);
                }
            }
            printf("
    ");
        }
        return 0;
    }
    

     4.CodeforcesRound #169 (Div. 2) ELittle Girl and Problem on Treeshttp://codeforces.com/contest/276/problem/E

       题意:给一个没有分支的树(即除了跟的入度加出度之和大于2以外,其他节点的值均小于等于2),然后给两种操作 第一种对于v节点d范围内的点的值均加上x 第二种查询v节点的值;

       题解:跑一遍dfs对所有节点编号建树 然后对于更新节点是否能达到根进行分类讨论 对于能超过根的进行树状数组维护以根为中心的圆区域即可;

      

    #include <bits/stdc++.h>
    #define N 100005
    using namespace std;
    vector<int>vec[N];
    int dep[N];int p[N];int fp[N];int ans=0;
    int b[N];int tt;int num[N];
    void dfs(int v,int pre,int deep){
        dep[v]=deep;p[v]=++ans;fp[p[v]]=v;tt=max(tt,deep);
        num[v]=1;
        for(int i=0;i<vec[v].size();i++){
            if(vec[v][i]!=pre){
                dfs(vec[v][i],v,deep+1);
                num[v]+=num[vec[v][i]];
            }
        }
    }
    typedef struct node{
        int l;int r;int date;
        int flag;
    }node;
    node d[N<<2];
    void built(int root,int l,int r){
        if(l==r){
            d[root].l=l;d[root].r=r;d[root].date=0;d[root].flag=0;
            return ;
        }
        int mid=(l+r)>>1;
        built(root<<1,l,mid);
        built(root<<1|1,mid+1,r);
        d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r;d[root].date=0;d[root].flag=0;
    }
    void push(int root){
        d[root<<1].date+=(d[root<<1].r-d[root<<1].l+1)*d[root].flag;
        d[root<<1|1].date+=(d[root<<1|1].r-d[root<<1|1].l+1)*d[root].flag;
        d[root<<1].flag+=d[root].flag;d[root<<1|1].flag+=d[root].flag;
        d[root].flag=0;
    }
    void update(int root,int l,int r,int t){
        if(l<=d[root].l&&d[root].r<=r){
            d[root].date+=(d[root].r-d[root].l+1)*t;d[root].flag+=t;
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) update(root<<1,l,r,t);
        if(r>mid)  update(root<<1|1,l,r,t);
        d[root].date=(d[root<<1].date+d[root<<1|1].date);
    }
    int ans1;
    void querty(int root,int v){
        if(d[root].l==d[root].r){
            ans1=d[root].date;
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(v<=mid) querty(root<<1,v);
        else querty(root<<1|1,v);
        d[root].date=(d[root<<1].date+d[root<<1|1].date);
    }
    int get_id(int x){ return x&(-x);}
    void date(int v,int t){
       // cout<<v<<" "<<t<<endl;
        for(int i=v;i<=tt;i+=get_id(i)){
            b[i]+=t;
           // cout<<b[i]<<endl;
        }
    }
    int quert(int v){
        int ans=0;
        for(int i=v;i>0;i-=get_id(i)) ans+=b[i];
        return ans;
    }
    int main(){
        int n,m;scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++){
            int t1,t2;scanf("%d%d",&t1,&t2);
            vec[t1].push_back(t2);vec[t2].push_back(t1);
        }
        tt=-1;
        ans=0;
        dfs(1,-1,1);
        //cout<<tt<<endl;
        built(1,1,n);
        for(int i=1;i<=m;i++){
            int t1;scanf("%d",&t1);
            if(t1==0){
                int v;int x;int d;
                scanf("%d%d%d",&v,&x,&d);
                if(v==1){
                    date(min(d+1,tt),x);continue;
                }
               // cout<<dep[v]-d<<endl;
                if(dep[v]-d>1){
                    int l=p[v]-d;int r;
                    if(num[v]-1>=d) r=p[v]+d;
                    else r=p[v]+num[v]-1;
                    update(1,l,r,x);
                }
                else{
                    int t=d-dep[v]+1;
                   // cout<<t<<endl;
                    date(min(t+1,tt),x);
                    int r;
                    if(num[v]-1>=d) r=p[v]+d;
                    else r=p[v]+num[v]-1;
                    int tt1=dep[fp[r]];
                    if(tt1>t+1) {int tt2=tt1-t-1;
                 //   cout<<r-tt2+1<<" "<<r<<endl;
                    update(1,r-tt2+1,r,x);}
                }
            }
            else if(t1==1){
                int v;scanf("%d",&v);
                if(v==1) {printf("%d
    ",quert(tt));continue;}
                querty(1,p[v]);
                printf("%d
    ",ans1+quert(tt)-quert(dep[v]-1));
            }
        }
        return 0;
    }
    

     5.CodeforcesBeta Round #35 (Div. 2) E. Paradehttp://codeforces.com/contest/35/problem/E

       题意:给你n个楼房的宽度和高度 问有多少个转折点

       题解:这题很骚的就是离散化的时候 应该每个两个直接留个空格 然后直接处理即可 对于每个位置只要高度不同就一定会产生贡献 然后分类讨论即可(小心文件输入

      

    #include <bits/stdc++.h>
    #define N 200005
    #define ll long long
    using namespace std;
    typedef struct node{
        ll x;ll y;int date;
        friend bool operator <(node aa,node bb){
            return aa.date<bb.date;
        }
    }node;
    node a[N<<2];
    vector<ll>vec;
    typedef struct node1{
        int l;int r;int date;
    }node1;
    node1 d[N<<3];
    int  b[N<<2];
    node p[N<<2];
    void built(int root,int l,int r){
        if(l==r){
            d[root].l=l;d[root].r=r;d[root].date=0;
            return ;
        }
        int mid=(l+r)>>1;
        built(root<<1,l,mid);
        built(root<<1|1,mid+1,r);
        d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r;d[root].date=0;
    }
    void push(int root){
        d[root<<1].date=max(d[root<<1].date,d[root].date);d[root<<1|1].date=max(d[root<<1|1].date,d[root].date);
    }
    void update(int root,int l,int r,int t){
        if(l<=d[root].l&&d[root].r<=r){
            d[root].date=max(t,d[root].date);
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) update(root<<1,l,r,t);
        if(r>mid) update(root<<1|1,l,r,t);
    }
    void querty(int root,int l,int r){
        if(d[root].l==d[root].r){
            b[d[root].l]=d[root].date;
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        querty(root<<1,l,mid);
        querty(root<<1|1,mid+1,r);
    }
    int main(){
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%I64d%I64d",&a[i].date,&a[i].x,&a[i].y);
            vec.push_back(a[i].x);vec.push_back(a[i].y);
        }
        sort(vec.begin(),vec.end());
        int t=unique(vec.begin(),vec.end())-vec.begin();
        for(int i=1;i<=n;i++){
            a[i].x=lower_bound(vec.begin(),vec.begin()+t,a[i].x)-vec.begin()+1;
            a[i].x=2*a[i].x;
            a[i].y=lower_bound(vec.begin(),vec.begin()+t,a[i].y)-vec.begin()+1;
            a[i].y=2*a[i].y;
        }
        built(1,1,2*t+10);
        for(int i=1;i<=n;i++){
            update(1,a[i].x,a[i].y,a[i].date);
        }
        querty(1,1,2*t+10);
        int ans=0;
         for(int i=2;i<=2*t+1;i++){
            if(b[i]>b[i-1]){
                p[++ans].x=vec[i/2-1];p[ans].y=b[i-1];
                p[++ans].x=vec[i/2-1];p[ans].y=b[i];
            }
            else if(b[i]<b[i-1]){
                p[++ans].x=vec[(i-1)/2-1];p[ans].y=b[i-1];
                p[++ans].x=vec[(i-1)/2-1];p[ans].y=b[i];
            }
        }
        printf("%d
    ",ans);
        for(int i=1;i<=ans;i++){
            printf("%I64d %I64d
    ",p[i].x,p[i].y);
        }
        return 0;
    }
    

     6.fzu2105 Digits Count:http://acm.fzu.edu.cn/problem.php?pid=2105

    题意:

     给你N个数,有四种操作。

    (1)"ANDopnL R",表示对区间[L,R]内的数全部与opn进行且(&)操作。

    (2)"OR opn L R",表示对区间[L,R]内的数全部与opn进行或(|)操作。

    (3)"XOR opn L R",表示对区间[L,R]内的数全部与opn进行异或(^)操作。

    (4)"SUMopnL R",求出区间[L,R]的数的和

     题解:首先根据元素范围0-16 所以转换为2进制最多4位 按位建树 然后分析几种运算的性质 确定维护标记的个数 注意线段树的不同写法会导致MLE 所以在一发MLE的时候 应选择比较存较少的东西实现即可;

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #define N 1000005
    using namespace std;
    typedef struct node{
        int flag1;int flag2;
        int sum;
    }node;
    node d[4][N<<2];
    int a[4][N];
    void up(int root,int t){
        d[t][root].sum=d[t][root<<1].sum+d[t][root<<1|1].sum;
    }
    void push(int t,int root,int r){
        if(d[t][root].flag1!=-1){
            d[t][root<<1].flag1=d[t][root].flag1;d[t][root<<1|1].flag1=d[t][root].flag1;
            d[t][root<<1].flag2=0;d[t][root<<1|1].flag2=0;
            d[t][root<<1].sum=(r-(r>>1))*d[t][root].flag1;
            d[t][root<<1|1].sum=((r>>1))*d[t][root].flag1;
            d[t][root].flag1=-1;
            if(d[t][root].flag2%2==1){
                d[t][root<<1].flag2=(d[t][root<<1].flag2+d[t][root].flag2%2)%2;
                d[t][root<<1|1].flag2=(d[t][root<<1|1].flag2+d[t][root].flag2%2)%2;
                d[t][root<<1].sum=(r-(r>>1))-d[t][root<<1].sum;
                d[t][root<<1|1].sum=((r>>1))-d[t][root<<1|1].sum;
            }
            d[t][root].flag2=0;
        }
        else{
            if(d[t][root].flag2%2==1){
                d[t][root<<1].flag2=(d[t][root<<1].flag2+d[t][root].flag2%2)%2;
                d[t][root<<1|1].flag2=(d[t][root<<1|1].flag2+d[t][root].flag2%2)%2;
                d[t][root<<1].sum=(r-(r>>1))-d[t][root<<1].sum;
                d[t][root<<1|1].sum=((r>>1))-d[t][root<<1|1].sum;
            }
            d[t][root].flag2=0;
        }
    }
    void built(int root,int l,int r,int t){
        if(l==r){
            d[t][root].flag1=-1;d[t][root].flag2=0;d[t][root].sum=a[t][l];
            return ;
        }
        int mid=(l+r)>>1;
        built(root<<1,l,mid,t);
        built(root<<1|1,mid+1,r,t);
        d[t][root].flag1=-1;d[t][root].flag2=0;
        up(root,t);
    }
    void update(int root,int l,int r,int t,int x,int l1,int r1){
        if(l<=l1&&r1<=r){
            d[t][root].flag1=x;d[t][root].flag2=0;
            d[t][root].sum=(r1-l1+1)*x;
            return ;
        }
        push(t,root,r1-l1+1);
        int mid=(l1+r1)>>1;
        if(l<=mid) update(root<<1,l,r,t,x,l1,mid);
        if(r>mid) update(root<<1|1,l,r,t,x,mid+1,r1);
        up(root,t);
    }
    void reses(int root,int l,int r,int t,int l1,int r1){
        if(l<=l1&&r1<=r){
            d[t][root].flag2++;
            d[t][root].sum=(r1-l1+1)-d[t][root].sum;
            return ;
        }
        push(t,root,r1-l1+1);
        int mid=(l1+r1)>>1;
        if(l<=mid) reses(root<<1,l,r,t,l1,mid);
        if(r>mid) reses(root<<1|1,l,r,t,mid+1,r1);
        up(root,t);
    }
    int ans;
    void querty(int root,int l,int r,int t,int l1,int r1){
        if(l<=l1&&r1<=r){
            ans+=d[t][root].sum;
            return ;
        }
        push(t,root,r1-l1+1);
        int mid=(l1+r1)>>1;
        if(l<=mid) querty(root<<1,l,r,t,l1,mid);
        if(r>mid) querty(root<<1|1,l,r,t,mid+1,r1);
        up(root,t);
    }
    int main(){
         int T;scanf("%d",&T);
         while(T--){
            int n,m;scanf("%d%d",&n,&m);
            int t;
            for(int i=1;i<=n;i++){
                scanf("%d",&t);
                a[0][i]=(t&1);a[1][i]=(t&2)==2?1:0;a[2][i]=(t&4)==4?1:0;a[3][i]=(t&8)==8?1:0;
            }
            for(int i=0;i<4;i++) built(1,1,n,i);
            char str[20];int t1,t2,t3,t4;int x,l,r;
            for(int i=1;i<=m;i++){
                scanf("%s",str);
                if(str[0]=='A'){
                    scanf("%d%d%d",&x,&l,&r);l++;r++;
                    t1=(x&1);t2=(x&2)==2?1:0;t3=(x&4)==4?1:0;t4=(x&8)==8?1:0;
                    if(t1==0) update(1,l,r,0,0,1,n);
                    if(t2==0) update(1,l,r,1,0,1,n);
                    if(t3==0) update(1,l,r,2,0,1,n);
                    if(t4==0) update(1,l,r,3,0,1,n);
                }
                else if(str[0]=='O'){
                    scanf("%d%d%d",&x,&l,&r);l++;r++;
                    t1=(x&1);t2=(x&2)==2?1:0;t3=(x&4)==4?1:0;t4=(x&8)==8?1:0;
                    if(t1==1) update(1,l,r,0,1,1,n);
                    if(t2==1) update(1,l,r,1,1,1,n);
                    if(t3==1) update(1,l,r,2,1,1,n);
                    if(t4==1) update(1,l,r,3,1,1,n);
                }
                else if(str[0]=='X'){
                    scanf("%d%d%d",&x,&l,&r);l++;r++;
                    t1=(x&1);t2=(x&2)==2?1:0;t3=(x&4)==4?1:0;t4=(x&8)==8?1:0;
                    if(t1==1) reses(1,l,r,0,1,n);
                    if(t2==1) reses(1,l,r,1,1,n);
                    if(t3==1) reses(1,l,r,2,1,n);
                    if(t4==1) reses(1,l,r,3,1,n);
                }
                else{
                    scanf("%d%d",&l,&r);l++;r++;
                    int sum=0;
                    for(int i=0;i<4;i++){
                        ans=0;querty(1,l,r,i,1,n);
                        sum+=(1<<i)*ans;
                    }
                    printf("%d
    ",sum);
                }
            }
         }
         return 0;
    }
  • 相关阅读:
    C#.NET常见问题(FAQ)-如何在不同窗体之间传递值
    C#.NET常见问题(FAQ)-如何不显示窗口的关闭按钮
    C#.NET常见问题(FAQ)-如何判断两个类是否相同类型
    C#.NET常见问题(FAQ)-如何判断某个字符是否为汉字
    C#.NET常见问题(FAQ)-如何改变字符串编码
    C# 多线程编程 ThreadStart ParameterizedThreadStart
    C# 线程调用主线程中的控件
    LINQ to XML 编程基础
    LINQ to XML 建立,读取,增,删,改
    WinForm 自动完成控件实例代码简析
  • 原文地址:https://www.cnblogs.com/wang9897/p/7811864.html
Copyright © 2011-2022 走看看