H Moving Points
题目链接:https://vjudge.net/contest/358745#problem/H
思路:树状数组维护,类似于树状数组求逆序对+思维(思维量很小)

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+9;
typedef long long ll;
struct node{
    ll a,b;
    friend bool operator <(node a,node b){
        return a.a<b.a;
    }
}a[N];
ll b[N];
ll h[N];
ll c1[N],c2[N];
int m,n;
void des(){
    sort(h+1,h+n+1);m=0;
    for(int i=1;i<=n;i++){
        if(i==1||h[i]!=h[i-1]){
            b[++m]=h[i];
        }
    }
}
int query(ll x){
    return lower_bound(b+1,b+m+1,x)-b;
}
int lowbit(int x){
    return x&(-x);
}
void update1(int x,ll v){
    for(int i=x;i<=m;i+=lowbit(i)){
        c1[i]+=v;
    }
// for(int i=1;i<=m;i++)cout<<c1[i]<<" ";puts("");
}
void update2(int x,ll v){
    for(int i=x;i<=m;i+=lowbit(i)){
        c2[i]+=v;
    }
}
ll query1(ll x){
    ll ans=0;
    for(ll i=x;i;i-=lowbit(i)){
        ans+=c1[i];
    }
    return ans;
}
ll query2(ll x){
    ll ans=0;
    for(int i=x;i;i-=lowbit(i)){
        ans+=c2[i];
    }
    return ans;
}

int main(){
// ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    while(~scanf("%d",&n)){
        m=0;
        memset(c1,0,sizeof c1);
        memset(c2,0,sizeof c2);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i].a);
        }
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i].b);
            h[i]=a[i].b;
        }
        des();
        sort(a+1,a+n+1);
        ll ans=0;
// for(int i=1;i<=m;i++){
// cout<<b[i]<<" ";
// }puts("");
        for(int i=1;i<=n;i++){
            int x=query(a[i].b);
            ll y=query1(x),z=query2(x);
// cout<<x<<endl;
            ans+=(y*a[i].a-z);
            update1(x,1ll);
            update2(x,a[i].a);
// cout<<y<<" "<<z<<endl;
        }
        printf("%lld\n",ans);
    }
}

I - Mayor’s posters
题目链接:https://vjudge.net/contest/358745#problem/I
思路:插点离散化+懒惰标记的应用

#include<iostream>
#include<vector>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+9;
typedef long long ll;
struct node{
    int l,r;
    int lazy;
}tree[N<<2];
int n;
void build(int rt,int l,int r){
    tree[rt].l=l,tree[rt].r=r;
    tree[rt].lazy=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
int L[N],R[N],ans[N];
vector<int>point;
void pushdown(int rt){
    if(tree[rt].lazy!=0){
        tree[rt<<1|1].lazy=tree[rt<<1].lazy=tree[rt].lazy;
        tree[rt].lazy=0;
    }
}
void change(int rt,int l,int r,int x){
    if(tree[rt].l>=l&&tree[rt].r<=r){
        tree[rt].lazy=x;
        return;
    }
    pushdown(rt);
    int mid=(tree[rt].l+tree[rt].r)>>1;
    if(l<=mid)change(rt<<1,l,r,x);
    if(r>mid)change(rt<<1|1,l,r,x);
}
void query(int rt,int l,int r){
    if(tree[rt].lazy){
        ans[tree[rt].lazy]=1;
        return;
    }
    pushdown(rt);
    if(tree[rt].l==tree[rt].r)return;
    int mid=(tree[rt].l+tree[rt].r)>>1;
    query(rt<<1,l,r);
    query(rt<<1|1,l,r);
}
int main(){
    int _;
    scanf("%d",&_);
    while(_--){
        scanf("%d",&n);point.clear();
        for(int i=1;i<=n;i++){
            scanf("%d%d",&L[i],&R[i]);
            point.push_back(L[i]);
            point.push_back(R[i]);
        }
        sort(point.begin(),point.end());
        point.erase(unique(point.begin(),point.end()),point.end());
        int m=point.size();
        for(int i=0;i<m-1;i++){
            if(point[i+1]-point[i]>1){
                point.push_back(point[i+1]-1);
            }
        }
        sort(point.begin(),point.end());
        m=point.size();
        build(1,0,m-1);memset(ans,0,sizeof ans);
        for(int i=1;i<=n;i++){
            int x=lower_bound(point.begin(),point.end(),L[i])-point.begin();
            int y=lower_bound(point.begin(),point.end(),R[i])-point.begin();
            change(1,x,y,i);
        }
        int res=0;query(1,0,m-1);
        for(int i=1;i<=n;i++){
            if(ans[i])res++;
        }
        printf("%d\n",res);
    }
}

J - Atlantis
题目链接:https://vjudge.net/contest/358745#problem/J
思路:课上讲过这里不在赘述,不过要注意c++11要用.f

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define debug puts("*");
const int N=220;
int n,cnt,t=1;
struct node{
    int l,r,cnt;
    double len;
}tree[N<<2];
struct knode{
    double x1,y1,y2;
    int k;
    friend bool operator <(knode a,knode b){
        return a.x1<b.x1;
    }
}line[N];
double raw[N],b[N],val[N];
void discrete(){
    sort(raw+1,raw+2*n+1);
// rep(i,1,2*n)cout<<raw[i]<<" ";puts("");
    rep(i,1,2*n)
        if(i==1||raw[i]!=raw[i-1])
            b[++cnt]=raw[i];
// rep(i,1,cnt)cout<<b[i]<<" ";
}
int findx(double x){
    return lower_bound(b+1,b+cnt+1,x)-b;
}
void pushup(int rt,int l,int r){
    if(tree[rt].cnt){
        tree[rt].len=b[r+1]-b[l];
    }
    else if(l!=r){
        tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;
    }else tree[rt].len=0;
    return ;
}
void build(int rt,int l,int r){
    tree[rt].l=l,tree[rt].r=r;
    tree[rt].len=0.0;tree[rt].cnt=0;
// cout<<l<<" "<<r<<endl;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
void update(int rt,int l,int r,int x){

    if(l<=tree[rt].l&&tree[rt].r<=r){
        tree[rt].cnt+=x;
        pushup(rt,tree[rt].l,tree[rt].r);
        return;
    }
    int mid=(tree[rt].l+tree[rt].r)>>1;   ///2
    if(l<=mid)update(rt<<1,l,r,x);
    if(r>mid)update(rt<<1|1,l,r,x);
    pushup(rt,tree[rt].l,tree[rt].r);
}
int main(){
    while(~scanf("%d",&n)){
        if(!n)break;
        cnt = 0;     /// 1
        rep(i,1,n){
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            raw[i*2-1]=y1,raw[i*2]=y2;
            line[i*2-1].x1=x1,line[i*2-1].y1=y1,line[i*2-1].y2=y2;
            line[i*2-1].k=1;
            line[i*2].x1=x2,line[i*2].y1=y1,line[i*2].y2=y2;
            line[i*2].k=-1;
        }
        discrete();
        sort(line+1,line+2*n+1);
        double ans=0;
        build(1,1,cnt);
        rep(i,1,2*n){
            ans+=tree[1].len*(line[i].x1-line[i-1].x1);
            update(1,findx(line[i].y1),findx(line[i].y2)-1,line[i].k);
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n", t++, ans);
    }
}

K - A Simple Problem with Integers
思路:课上例题,lazy标记应用

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+9;
struct node{
    ll l,r;
    ll data,add;
}m[N<<2];
ll a[N];
void pushdown(ll rt,ll len){
    if(m[rt].add){
        m[rt<<1].add+=m[rt].add;
        m[rt<<1|1].add+=m[rt].add;
        m[rt<<1].data+=(m[rt].add*((ll)len-(len>>1)));
        m[rt<<1|1].data+=(m[rt].add*((ll)len>>1));
        m[rt].add=0;
    }
}
void build(ll rt,ll l,ll r){
    m[rt].l=l;
    m[rt].r=r;
    m[rt].add=0;
    if(l==r){
        m[rt].data=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    m[rt].data=m[rt<<1].data+m[rt<<1|1].data;
}
void update(ll l,ll r,ll v,ll rt){
    if(l<=m[rt].l&&r>=m[rt].r){
        m[rt].add+=v;
        m[rt].data+=(v*(m[rt].r-m[rt].l+1ll));
        return;
    }
    pushdown(rt,m[rt].r-m[rt].l+1);
    int mid=(m[rt].r+m[rt].l)>>1;
    if(mid>=l)update(l,r,v,rt<<1);
    if(mid<r)update(l,r,v,rt<<1|1);
    m[rt].data=m[rt<<1|1].data+m[rt<<1].data;
}
ll query(ll l,ll r,ll p){
    if(m[p].l>=l&&m[p].r<=r){
        return m[p].data;
    }
    int mid=(m[p].l+m[p].r)>>1;
    pushdown(p,m[p].r-m[p].l+1);
    ll ans=0;
    if(mid>=l)ans+=query(l,r,p<<1);
    if(mid<r)ans+=query(l,r,p<<1|1);
    return ans;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    build(1,1,n);
    while(m--){
        char c[4];
        scanf("%s",c);
        ll x,y;ll z;
        if(c[0]=='Q'){
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",query(x,y,1));
        }
        else{
            scanf("%lld%lld%lld",&x,&y,&z);
            update(x,y,z,1);
        }
    }
}

L - Black And White
思路:区间合并的典型例题,最好自己写一遍,我写的时候出了太多bug,这个代码还是借用的。。。
这里更新一下,贴上我自己的代码,原来是懒惰标记忘记清空了,实在是太菜了

#include<bits/stdc++.h>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
const int N=1e5+9;
int a[N],n,m;
int tree0[N<<2],tree1[N<<2],lazy[N<<2],lmax0[N<<2];
int lmax1[N<<2],rmax0[N<<2],rmax1[N<<2];

void swp(int rt){
    swap(tree0[rt],tree1[rt]);
    swap(rmax0[rt],rmax1[rt]);
    swap(lmax0[rt],lmax1[rt]);
    return;
}

void pushup(int rt){
    if(!tree0[lson])lmax1[rt]=lmax1[lson]+lmax1[rson];
    else lmax1[rt]=lmax1[lson];
    if(!tree1[lson])lmax0[rt]=lmax0[lson]+lmax0[rson];
    else lmax0[rt]=lmax0[lson];
    if(!tree0[rson])rmax1[rt]=rmax1[rson]+rmax1[lson];
    else rmax1[rt]=rmax1[rson];
    if(!tree1[rson])rmax0[rt]=rmax0[rson]+rmax0[lson];
    else rmax0[rt]=rmax0[rson];
    tree0[rt]=max(rmax0[lson]+lmax0[rson],max(tree0[lson],tree0[rson]));
    tree0[rt]=max(tree0[rt],max(tree0[lson],tree0[rson]));
    tree0[rt]=max(tree0[rt],max(lmax0[rt],rmax0[rt]));

    tree1[rt]=max(rmax1[lson]+lmax1[rson],max(tree1[lson],tree1[rson]));
    tree1[rt]=max(tree1[rt],max(tree1[lson],tree1[rson]));
    tree1[rt]=max(tree1[rt],max(lmax1[rt],rmax1[rt]));
}
void pushdown(int rt){
    if(lazy[rt]){
        swp(lson);
        swp(rson);
        lazy[lson]^=1;
        lazy[rson]^=1;
        lazy[rt]=0;
    }
    return;
}
void build(int rt,int l,int r){
    lazy[rt]=0;
    if(l==r){
        scanf("%d",&a[l]);
        if(a[l]==1){
            tree0[rt]=0;tree1[rt]=1;
            lmax0[rt]=0;rmax0[rt]=0;
            lmax1[rt]=1;rmax1[rt]=1;
        }
        else{
            tree0[rt]=1;tree1[rt]=0;
            lmax0[rt]=1;rmax0[rt]=1;
            lmax1[rt]=0;rmax1[rt]=0;
        }
// cout<<l<<endl;
        return;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(rt);
}
void change(int rt,int l,int r,int x,int y){
    if(l>=x&&r<=y){
        lazy[rt]^=1;
        swp(rt);
        return;
    }
    int mid=(l+r)>>1;
    pushdown(rt);
    if(x<=mid)change(lson,l,mid,x,y);
    if(y>mid)change(rson,mid+1,r,x,y);
    pushup(rt);
}
int query(int rt,int l,int r,int x,int y){
    if(l>=x&&r<=y){
        return tree1[rt];
    }
    int ans=0;
    pushdown(rt);
    int mid=(l+r)>>1;
    if(x<=mid){ans=max(query(lson,l,mid,x,y),ans);}
    if(y>mid){ans=max(query(rson,mid+1,r,x,y),ans);}
    ans=max(ans,min(mid-x+1,rmax1[lson])+min(y-mid,lmax1[rson]));
    return ans;
}
int main(){
    while(~scanf("%d",&n)){
        build(1,1,n);

        scanf("%d",&m);
        while(m--){
            int op,l,r;
            scanf("%d%d%d",&op,&l,&r);
            if(op==0){
                printf("%d\n",query(1,1,n,l,r));
            }
            else{
                change(1,1,n,l,r);
            }
// for(int i=1;i<=4*n;i++){
// printf("%d ",tree1[i]);
// }puts("");
        }
    }
}
#include <bits/stdc++.h>

#define LS(a) (a << 1)
#define RS(a) (a << 1 | 1)
#define NS (100005)

using namespace std;


struct N {int l1, r1, m1, l0, r0, m0, tag;} e[NS << 2];

int n, m, arr[NS];

void Swp(int a)
{
    swap(e[a].l1, e[a].l0);
    swap(e[a].r1, e[a].r0);
    swap(e[a].m1, e[a].m0);
}

void pup(int a)
{
    int l = LS(a), r = RS(a);
    if (!e[l].m0) e[a].l1 = e[l].l1 + e[r].l1;
    else e[a].l1 = e[l].l1;
    if (!e[r].m0) e[a].r1 = e[r].r1 + e[l].r1;
    else e[a].r1 = e[r].r1;
    if (!e[l].m1) e[a].l0 = e[l].l0 + e[r].l0;
    else e[a].l0 = e[l].l0;
    if (!e[r].m1) e[a].r0 = e[r].r0 + e[l].r0;
    else e[a].r0 = e[r].r0;
    e[a].m0 = max(e[l].r0 + e[r].l0, max(e[l].m0, e[r].m0));
    e[a].m1 = max(e[l].r1 + e[r].l1, max(e[l].m1, e[r].m1));
}

void pdown(int a)
{
    if (!e[a].tag) return;
    Swp(LS(a)), Swp(RS(a));
    e[LS(a)].tag ^= 1, e[RS(a)].tag ^=1, e[a].tag = 0;
}

void Build(int L = 1, int R = n, int a = 1)
{
    memset(&e[a], 0, sizeof(N));
    if (L == R)
    {
        if (arr[L]) e[a].l1 = e[a].r1 = e[a].m1 = 1;
        else e[a].l0 = e[a].r0 = e[a].m0 = 1;
        return;
    }
    int Mid = (L + R) >> 1;
    Build(L, Mid, LS(a)), Build(Mid + 1, R, RS(a)), pup(a);
}

void Rev(int l, int r, int L = 1, int R = n, int a = 1)
{
    if (l <= L && R <= r) {Swp(a), e[a].tag ^= 1; return;}
    pdown(a); int Mid = (L + R) >> 1;
    if (l <= Mid) Rev(l, r, L, Mid, LS(a));
    if (r > Mid) Rev(l, r, Mid + 1, R, RS(a));
    pup(a);
}

int Query(int l, int r, int L = 1, int R = n, int a = 1)
{
    if (l <= L && R <= r) return e[a].m1;
    pdown(a); int Mid = (L + R) >> 1, res = 0;
    if (l <= Mid) res = max(res, Query(l, r, L, Mid, LS(a)));
    if (r > Mid) res = max(res, Query(l, r, Mid + 1, R, RS(a)));
    res = max(res, min(Mid - l + 1, e[LS(a)].r1) + min(r - Mid, e[RS(a)].l1));
    return res;
}

int main(int argc, char const* argv[])
{
    while (~scanf("%d", &n))
    {
        for (int i = 1; i <= n; i += 1) scanf("%d",&arr[i]);
        Build();scanf("%d",&m);
        for (int c = 1, o, l, r; c <= m; c += 1)
        {
            scanf("%d%d%d",&o,&l,&r);
            if (o) Rev(l, r);
            else printf("%d\n", Query(l, r));
        }
    }
    return 0;
}


2019ICPC上海网络赛 - A. Lightning Routing I
网络赛的题,知识点略深可不看,下面有篇博客
https://blog.csdn.net/weixin_44059127/article/details/100941413
思路:动态维护直径+LCA