整体二分合集

搞了一下整体二分,说一下自己的体会.

其实我个人感觉,整体二分和cdq分治在感觉上差不多,写起来其实区别也不大.整体二分其实算是二分答案的升级版,二分答案后对所有询问进行分类,然后用cdq分治中的操作进行询问排序,然后存答案输出.大体上是这样的一个算法.

区间二分有的时候可以省略一些复杂的数据结构,所以还是很资瓷的啊.

 

k大数查询:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
#include<complex>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
#define mp make_pair
#define cp complex<db> 
#define enter puts("")
#define int long long
const long long INF = 1LL << 60;
const double eps = 1e-8;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
struct node
{
    int kind,l,r,v,num,c,ans;
}a[50005];
int n,m;
struct tree
{
    int v,lazy;
    bool p;
}t[131072];
bool cmp1(node x,node y)
{
    return x.c < y.c;
}
bool cmp2(node x,node y)
{
    return x.num < y.num;
}
/*void push_down(int o,int l,int r)
{
    if(t[o].p == true)
    {
        t[o].p = false;
        t[o >> 1].v = t[o >> 1 | 1].v = 0;
        t[o >> 1].lazy = t[o >> 1 | 1].lazy = 0;
        t[o >> 1].p = t[o >> 1 | 1].p = true;
        return;
    }
    if(t[o].lazy != 0)
    {
        int mid = (l + r) >> 1;
        t[o >> 1].lazy = t[o >> 1 | 1].lazy = t[o].lazy;
        t[o >> 1].lazy = (mid - l + 1) * t[o].lazy;
        t[o >> 1 | 1].lazy = (r - l) * t[o].lazy;
        t[o].lazy = 0;
    }
}*/
void push_down(int num,int l,int r){
    if(l==r)return;
    if(t[num].p){//更新儿子; 
        t[num*2].v=t[num*2+1].v=0;
        t[num*2].lazy=t[num*2+1].lazy=0;
        t[num*2].p=t[num*2+1].p=1;
        t[num].p=0;
    }
    int mid=(l+r)/2;
    t[num*2].v+=(mid-l+1)*t[num].lazy;
    t[num*2+1].v+=(r-(mid+1)+1)*t[num].lazy;
    t[num*2].lazy+=t[num].lazy;
    t[num*2+1].lazy+=t[num].lazy;
    t[num].lazy=0;
}
void init(int num,int l,int r,int x,int y)
{
    push_down(num,l,r);
    if(x == l && r == y)
    {
        t[num].v += (r - l + 1) * 1;
        t[num].lazy += 1;
        return;
    }
    int mid = (l + r) >> 1;
    if(y <= mid)
    init(num << 1,l,mid,x,y);
    else if(x > mid)
    init(num << 1 | 1,mid + 1,r,x,y);
    else
    {
        init(num << 1,l,mid,x,mid);
        init(num << 1 | 1,mid + 1,r,mid + 1,y);
    }
    t[num].v = t[num << 1].v + t[num << 1 | 1].v;
}
int outit(int num,int l,int r,int x,int y)
{
    push_down(num,l,r);
    if(x == l && r == y) return t[num].v;
    int mid = (l + r) >> 1;
    if(y <= mid)
    return outit(num << 1,l,mid,x,y);
    else if(x > mid)
    return outit(num << 1 | 1,mid + 1,r,x,y);
    else
    {
        return outit(num << 1,l,mid,x,mid) + outit(num << 1 | 1,mid + 1,r,mid + 1,y);
    }
}
/*int outit(int num,int l,int r,int x,int y){
    push_down(num,l,r);
    if(x<=l&&r<=y)return t[num].v;
    int mid=l+r>>1;
    int ans=0;
    if(mid  >=x)ans+=outit(num<<1,l,mid  ,x,y);
    if(mid+1<=y)ans+=outit(num<<1|1,mid+1,r,x,y);
    return ans;
}*/
void solve(int l,int r,int x,int y)
{
//    cout<<l<<" "<<r<<" "<<x<<" "<<y<<endl;
    if(l == r)
    {
        duke(i,x,y)
        a[i].ans = l;
        return;
    }
    int mid = (l + r) >> 1;
    int L = 0,R = y;
    t[1].v = t[1].lazy = 0;
    t[1].p = 1;
    for(int i = x;i <= y;i++)
    {
        if(a[i].kind == 1)
        {
            if(a[i].v <= mid)
            a[i].c = ++L;
            else
            {
                a[i].c = ++ R;
                init(1,1,n,a[i].l,a[i].r);
            }
        }
        else
        {
            int temp = outit(1,1,n,a[i].l,a[i].r);
            if(temp < a[i].v)
            {
                a[i].v -= temp;
                a[i].c = ++L;
            }
            else
            a[i].c = ++R;
        }
    }
    sort(a + x,a + y + 1,cmp1);
    solve(l,mid,x,x + L - 1);
    solve(mid + 1,r,x + L,y);
}
main()
{
//    freopen("3332.in","r",stdin);
    read(n); read(m);
    duke(i,1,m)
    {
        read(a[i].kind); read(a[i].l);
        read(a[i].r);read(a[i].v);
        a[i].num = i;
    }
    solve(-n,n,1,m);
    sort(a + 1,a + m + 1,cmp2);
    duke(i,1,m)
    {
        if(a[i].kind == 2)
        {
            printf("%d\n",a[i].ans);
        }
    }
    return 0;
}

[POI2011]MET-Meteors:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;i++)
#define lv(i,a,n) for(register int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 300005;
int l[N],r[N],val[N];
int n,m,tmp[N],k,t,ans[N],id[N],p[N];
ll tr[N];
vector <int> a[N];
bool mark[N];
int lowbit(int x)
{
    return x & -x;
}
ll query(int x)
{
    ll tmp = 0;
    while(x)
    {
        tmp += tr[x];
        x -= lowbit(x);
    }
    return tmp;
}
void add(int x,int v)
{
    while(x <= m)
    {
        tr[x] += v;
        x += lowbit(x);
    }
}
void opera(int g,int f)
{
    if(l[g] <= r[g])
    {
        add(l[g],f * val[g]);
        add(r[g] + 1,f * (-val[g]));
    }
    else
    {
        add(1,f * val[g]);
        add(r[g] + 1,f * (-val[g]));
        add(l[g],f * val[g]);
    }
}
void solve(int l,int r,int L,int R)
{
    if(l > r) return;
    if(L == R)
    {
        duke(i,l,r)
        ans[id[i]] = L;
        return;
    }
    int mid = (L + R) >> 1;
    while(t <= mid) t++,opera(t,1);
    while(t > mid) opera(t,-1),t--;
    int cnt = 0,now;
    ll tot;
    duke(i,l,r)
    {
        tot = 0;
        now = id[i];
        for(int j = 0;j < (int)a[now].size();j++)
        {
            tot += query(a[now][j]);
            if(tot >= p[now]) break;
        }
        if(tot >= p[now]) mark[now] = 1,cnt++;
        else
        mark[now] = 0;
    }
    int l1 = l,l2 = l + cnt;
    duke(i,l,r)
    {
        if(mark[id[i]]) tmp[l1++] = id[i];
        else
        tmp[l2++] = id[i];
    }
    duke(i,l,r)
    id[i] = tmp[i];
    solve(l,l1 - 1,L,mid);
    solve(l1,l2 - 1,mid + 1,R);
}
int main()
{
    read(n);read(m);
    duke(i,1,m)
    {
        int x;
        read(x);
        a[x].push_back(i);
    }
    duke(i,1,n)
    read(p[i]);
    read(k);
    duke(i,1,k)
    {
        read(l[i]);
        read(r[i]);
        read(val[i]);
    }
    k++;
    l[k] = 1; r[k] = m;val[k] = INF;
    duke(i,1,n)
    id[i] = i;
    solve(1,n,1,k);
    duke(i,1,n)
    {
        if(ans[i] != k)
        printf("%d\n",ans[i]);
        else
        puts("NIE");
    }
    return 0;
}

[国家集训队]矩阵乘法:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
#include<complex>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
#define mp make_pair
#define cp complex<db>
#define enter puts("")
const long long INF = 1LL << 60;
const double eps = 1e-8;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 510,Q = 60005;
struct node
{
    int x,y,v;
    bool operator < (const node &oth) const
    {
        return v < oth.v;
    }
}mat[N * N];
int mcnt,id[Q];
int n,q;
struct BIT
{
    int c[N][N];
    int n;
    BIT()
    {
        clean(c);
        n = 0;
    }
    int lowbit(int x)
    {
        return x & -x;
    }
    void add(int x,int y,int v)
    {
        for(int i = x;i <= n;i += lowbit(i))
        {
            for(int j = y;j <= n;j += lowbit(j))
            {
                c[i][j] += v;
            }
        }
    }
    int query(int x,int y)
    {
        int ans = 0;
        for(int i = x;i > 0;i -= lowbit(i))
        {
            for(int j = y;j > 0;j -= lowbit(j))
            {
                ans += c[i][j];
            }
        }
        return ans;
    }
    int sub(int x1,int y1,int x2,int y2)
    {
        int ans = query(x2,y2);
        ans -= query(x1 - 1,y2) + query(x2,y1 - 1);
        ans += query(x1 - 1,y1 - 1);
        return ans;
    }
}bit;
struct events
{
    int x1,x2,y1,y2,k;
    void input()
    {
        read(x1);read(y1);
        read(x2);read(y2);
        read(k);
    }
}qu[Q];
int ans[Q],cur[Q];
int t1[Q],t2[Q];
int bcount(events a)
{
    return bit.sub(a.x1,a.y1,a.x2,a.y2);
}
void solve(int l,int r,int x,int y)
{
    // cout<<l<<" "<<r<<" "<<x<<" "<<y<<endl;
    if(x > y) return;
    if(l == r)
    {
        duke(i,x,y)
        ans[id[i]] = mat[l].v;
        return;
    }
    int mid = (l + r) >> 1;
    duke(i,l,mid)
    {
        bit.add(mat[i].x,mat[i].y,1);
    }
    int cnt1 = 0,cnt2 = 0;
    for(int i = x;i <= y;i++)
    {
        int u = id[i];
        int s = cur[u] + bcount(qu[u]);
        if(s >= qu[u].k) t1[++cnt1] = u;
        else t2[++cnt2] = u,cur[u] = s;
    }
    int qcnt = x - 1;
    duke(i,1,cnt1)
    id[++qcnt] = t1[i];
    duke(i,1,cnt2)
    id[++qcnt] = t2[i];
    for(int i = l;i <= mid;i++)
    bit.add(mat[i].x,mat[i].y,-1);
    solve(l,mid,x,x + cnt1 - 1);
    solve(mid + 1,r,x + cnt1,y);
}
int main()
{
    // freopen("1527.in",?"r",stdin);
    read(n); read(q);
    bit.n = n;
    duke(i,1,n)
    {
        duke(j,1,n)
        {
            int x;
            read(x);
            mat[++mcnt] = (node){i,j,x};
        }
    }
    sort(mat + 1,mat + mcnt + 1);
    duke(i,1,q)
    {
        qu[i].input();
    }
    duke(i,1,q)
    {
        id[i] = i;
    }
    solve(1,mcnt,1,q);
    duke(i,1,q)
    {
        printf("%d\n",ans[i]);
    }
    return 0;
}

 

posted @ 2018-12-14 11:34  DukeLv  阅读(146)  评论(0编辑  收藏  举报