整体二分合集
搞了一下整体二分,说一下自己的体会.
其实我个人感觉,整体二分和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; }
#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; }
只想找一个不会伤害我的人