线段树
感觉线段树一直学的不好,从开始学到现在换了很多风格,模板其实不是问题,关键是还是思路吧。
从水题,开始再来一遍。
#include <iostream> #include <cstdio> #include <string> #include <map> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define MOD 1000000009 #define N 50000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int p[4*N]; void pushup(int rt) { p[rt] = p[rt<<1] + p[rt<<1|1]; } void build(int l,int r,int rt) { int m; if(l == r) { scanf("%d",&p[rt]); return ; } m = (l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int x,int sc,int l,int r,int rt) { int m; if(l == r) { p[rt] += sc; return ; } m = (l+r)>>1; if(x <= m) update(x,sc,lson); else update(x,sc,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt) { int m,sum = 0; if(l >= L&&r <= R) { return p[rt]; } m = (l+r)>>1; if(L <= m) sum += query(L,R,lson); if(R > m) sum += query(L,R,rson); return sum; } int main() { int t,cas = 1,a,b,n; char str[101]; scanf("%d",&t); while(t--) { scanf("%d",&n); build(1,n,1); printf("Case %d:\n",cas++); for(;;) { scanf("%s",str); if(str[0] == 'E') break; if(str[0] == 'Q') { scanf("%d%d",&a,&b); printf("%d\n",query(a,b,1,n,1)); } else if(str[0] == 'A') { scanf("%d%d",&a,&b); update(a,b,1,n,1); } else { scanf("%d%d",&a,&b); update(a,-b,1,n,1); } } } return 0; }
#include <iostream> #include <cstdio> #include <string> #include <map> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define N 100001 int p[4*N]; int lz[4*N]; void pushup(int rt) { p[rt] = p[rt<<1] + p[rt<<1|1]; } void pushdown(int rt,int m) { if(lz[rt]) { lz[rt<<1] = lz[rt]; lz[rt<<1|1] = lz[rt]; p[rt<<1] = lz[rt]*(m-(m>>1)); p[rt<<1|1] = lz[rt]*(m>>1); lz[rt] = 0; } } void build(int l,int r,int rt) { int m; lz[rt] = 0; if(l == r) { p[rt] = 1; return ; } m = (l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int L,int R,int sc,int l,int r,int rt) { if(L <= l&&R >= r) { lz[rt] = sc; p[rt] = (r-l+1)*sc; return ; } int m = (l+r)>>1; pushdown(rt,r-l+1); if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt) { int m,sum = 0; if(L <= l&&R >= r) { return p[rt]; } m = (l+r)>>1; pushdown(rt,r-l+1); if(L <= m) sum += query(L,R,lson); if(R > m) sum += query(L,R,rson); return sum; } int main() { int t,cas = 1,i,n,m,x,y,z; scanf("%d",&t); while(t--) { scanf("%d",&n); build(1,n,1); scanf("%d",&m); for(i = 1;i <= m;i ++) { scanf("%d%d%d",&x,&y,&z); update(x,y,z,1,n,1); } printf("Case %d: The total value of the hook is %d.\n",cas++,query(1,n,1,n,1)); } return 0; }
以前用线段树+二分做的,这次换了一个思路,把插过为0,没插过为1,利用find函数,查找。
#include <iostream> #include <cstdio> #include <string> #include <map> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define N 50001 int p[4*N],lz[4*N]; void pushup(int rt) { p[rt] = p[rt<<1] + p[rt<<1|1]; } void pushdown(int rt,int m) { if(lz[rt] != -1) { lz[rt<<1] = lz[rt]; lz[rt<<1|1] = lz[rt]; p[rt<<1] = lz[rt]*(m-(m>>1)); p[rt<<1|1] = lz[rt]*(m>>1); lz[rt] = -1; } } void build(int l,int r,int rt) { int m; lz[rt] = -1; if(l == r) { p[rt] = 1; return ; } m = (l + r)>>1; build(lson); build(rson); pushup(rt); } void update(int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { lz[rt] = sc; p[rt] = (r-l+1)*sc; return ; } pushdown(rt,r-l+1); m = (l + r)>>1; if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt) { int m,sum = 0; if(l >= L&&r <= R) { return p[rt]; } pushdown(rt,r-l+1); m = (l+r)>>1; if(L <= m) sum += query(L,R,lson); if(R > m) sum += query(L,R,rson); return sum; } int find(int x,int l,int r,int rt) { int m; if(l == r) { return l; } pushdown(rt,r-l+1); m = (l+r)>>1; if(x <= p[rt<<1]) return find(x,lson); else return find(x-p[rt<<1],rson); } int main() { int t,n,m,i,k,a,b,temp,l,r; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); build(0,n-1,1); for(i = 1;i <= m;i ++) { scanf("%d%d%d",&k,&a,&b); if(k == 1) { temp = query(a,n-1,0,n-1,1); if(temp == 0) { printf("Can not put any one.\n"); continue; } b = min(b,temp); if(a == 0) temp = 0; else temp = query(0,a-1,0,n-1,1); l = find(temp+1,0,n-1,1); r = find(temp+b,0,n-1,1); printf("%d %d\n",l,r); update(l,r,0,0,n-1,1); } else { printf("%d\n",b-a+1-query(a,b,0,n-1,1)); update(a,b,1,0,n-1,1); } } printf("\n"); } return 0; }
注意这是一段的染色。挺简单的,1Y.
#include <iostream> #include <cstdio> #include <string> #include <map> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define N 8001 int p[4*N],lz[4*N]; int flag[N],o[N]; void pushdown(int rt) { if(lz[rt] != -1) { lz[rt<<1] = lz[rt]; lz[rt<<1|1] = lz[rt]; p[rt<<1] = lz[rt]; p[rt<<1|1] = lz[rt]; lz[rt] = -1; } } void update(int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { lz[rt] = sc; p[rt] = sc; return ; } pushdown(rt); m = (l + r) >>1; if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); } void query(int l,int r,int rt) { int m; if(l == r) { o[l] = p[rt]; return ; } m = (l + r)>>1; pushdown(rt); query(lson); query(rson); } int main() { int n,i,x1,x2,c; while(scanf("%d",&n)!=EOF) { memset(flag,0,sizeof(flag)); memset(o,0,sizeof(o)); memset(p,-1,sizeof(p)); memset(lz,-1,sizeof(lz)); for(i = 0;i < n;i ++) { scanf("%d%d%d",&x1,&x2,&c); if(x1 <= x2-1) update(x1,x2-1,c,0,8000,1); } query(0,8000,1); for(i = 1;i <= 8000;i ++) { if(o[i] != o[i-1]) { if(o[i-1] != -1) flag[o[i-1]] ++; } } if(o[8000] != -1) flag[o[8000]] ++; for(i = 0;i <= 8000;i ++) { if(flag[i]) printf("%d %d\n",i,flag[i]); } printf("\n"); } return 0; }
和4614类似,注意待在原地的时候,方向不变。
#include <iostream> #include <cstdio> #include <string> #include <map> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define N 100001 int p[4*N]; void pushup(int rt) { p[rt] = p[rt<<1] + p[rt<<1|1]; } void update(int x,int sc,int l,int r,int rt) { int m; if(l == r) { p[rt] += sc; return ; } m = (l+r)>>1; if(x <= m) update(x,sc,lson); else update(x,sc,rson); pushup(rt); } int find(int x,int l,int r,int rt) { int m; if(l == r) { return l; } m = (l + r) >>1; if(x <= p[rt<<1]) return find(x,lson); else return find(x-p[rt<<1],rson); } int query(int L,int R,int l,int r,int rt) { int m,sum = 0; if(l >= L&&r <= R) { return p[rt]; } m = (l + r)>>1; if(L <= m) sum += query(L,R,lson); if(R > m) sum += query(L,R,rson); return sum; } int Abs(int x) { if(x < 0) return -x; return x; } int main() { int t,n,m,cas = 1,i,k,x,pre,l,r,flag,temp; scanf("%d",&t); while(t--) { memset(p,0,sizeof(p)); int ans = 0; scanf("%d%d",&n,&m); pre = 0; flag = -1; for(i = 0;i < m;i ++) { scanf("%d",&k); if(k == 0) { scanf("%d",&x); update(x,1,0,n,1); } else { temp = query(0,pre,0,n,1); if(p[1] == 0) continue; if(temp == 0) l = -100000000; else l = find(temp,0,n,1); if(p[1] == temp) r = 1000000000; else r = find(temp+1,0,n,1); int te = pre; if(l == pre) { update(l,-1,0,n,1); continue; } if(pre - l > r - pre) { pre = r; flag = 1; update(r,-1,0,n,1); } else if(pre - l < r - pre) { pre = l; flag = 0; update(l,-1,0,n,1); } else if(flag) { pre = r; update(r,-1,0,n,1); } else { pre = l; update(l,-1,0,n,1); } ans += Abs(te-pre); } } printf("Case %d: %d\n",cas++,ans); } return 0; }
HDU 1394 Minimum Inversion Number
求逆序数,当移动的时候,我居然毫无想法,看了题解发现如此简单啊....菜啊!!!!
#include <iostream> #include <cstdio> #include <string> #include <map> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define N 10001 int p[4*N]; int flag[N]; int s[N]; void pushup(int rt) { p[rt] = p[rt<<1] + p[rt<<1|1]; } void update(int x,int sc,int l,int r,int rt) { int m; if(l == r) { p[rt] = sc; return ; } m = (l + r)>>1; if(x <= m) update(x,sc,lson); else update(x,sc,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt) { int m,sum = 0; if(l >= L&&r <= R) { return p[rt]; } m = (l + r)>>1; if(L <= m) sum += query(L,R,lson); if(R > m) sum += query(L,R,rson); return sum; } int main() { int n,i,sum,ans; while(scanf("%d",&n)!=EOF) { memset(flag,0,sizeof(flag)); memset(p,0,sizeof(p)); for(i = 0;i < n;i ++) { scanf("%d",&s[i]); flag[s[i]] = i; } sum = 0; for(i = n-1;i >= 0;i --) { if(flag[i] != 0) { sum += query(0,flag[i]-1,0,n-1,1); } update(flag[i],1,0,n-1,1); } ans = sum; for(i = 0;i < n;i ++) { sum -= s[i]; sum += n-1-s[i]; ans = min(ans,sum); } printf("%d\n",ans); } return 0; }
模板题。
#include <iostream> #include <cstdio> #include <string> #include <map> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define N 50001 int minz[4*N],maxz[4*N]; void pushup(int rt) { minz[rt] = min(minz[rt<<1],minz[rt<<1|1]); maxz[rt] = max(maxz[rt<<1],maxz[rt<<1|1]); } void build(int l,int r,int rt) { int m; if(l == r) { scanf("%d",&minz[rt]); maxz[rt] = minz[rt]; return ; } m = (l + r)>>1; build(lson); build(rson); pushup(rt); } int qmax(int L,int R,int l,int r,int rt) { int m,ans = -1; if(l >= L&&r <= R) { return maxz[rt]; } m = (l + r)>>1; if(L <= m) ans = max(ans,qmax(L,R,lson)); if(R > m) ans = max(ans,qmax(L,R,rson)); return ans; } int qmin(int L,int R,int l,int r,int rt) { int m,ans = 100000000; if(l >= L&&r <= R) { return minz[rt]; } m = (l + r)>>1; if(L <= m) ans = min(ans,qmin(L,R,lson)); if(R > m) ans = min(ans,qmin(L,R,rson)); return ans; } int main() { int n,m,i,x,y; while(scanf("%d%d",&n,&m)!=EOF) { build(1,n,1); for(i = 0;i < m;i ++) { scanf("%d%d",&x,&y); printf("%d\n",qmax(x,y,1,n,1)-qmin(x,y,1,n,1)); } } return 0; }
ZOJ 3772 Calculate the Function
这题主要是想到矩阵+线段树,就好做了。注意矩阵乘法的顺序会影响最后的结果,倒这把矩阵乘起来。
#include <cstdio> #include <cstring> #include <string> #include <map> using namespace std; #define N 100001 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define MOD 1000000007 #define LL long long struct node { LL s[2][2]; } mat[4*N]; int p[4*N]; int num; node mul(node a,node b) { node c; int i,j,k; for(i = 0; i < 2; i ++) { for(j = 0; j < 2; j ++) c.s[i][j] = 0; } for(i = 0; i < 2; i ++) { for(j = 0; j < 2; j ++) { for(k = 0; k < 2; k ++) { c.s[i][j] += (a.s[i][k] * b.s[k][j])%MOD; c.s[i][j] %= MOD; } } } return c; } void pushup(int rt) { mat[rt] = mul(mat[rt<<1|1],mat[rt<<1]); } void build(int l,int r,int rt) { int m; if(l == r) { scanf("%d",&mat[rt].s[0][1]); p[num++] = mat[rt].s[0][1]; mat[rt].s[0][0] = 1; mat[rt].s[1][1] = 0; mat[rt].s[1][0] = 1; return ; } m = (l + r)>>1; build(lson); build(rson); pushup(rt); } node query(int L,int R,int l,int r,int rt) { int m; if(l >= L&&r <= R) { return mat[rt]; } node sum; sum.s[0][0] = sum.s[1][1] = 1; sum.s[0][1] = sum.s[1][0] = 0; m = (l + r)>>1; if(L <= m) sum = mul(query(L,R,lson),sum); if(R > m) sum = mul(query(L,R,rson),sum); return sum; } int main() { int t,n,m,i,l,r; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); num = 1; build(1,n,1); for(i = 0; i < m; i ++) { scanf("%d%d",&l,&r); if(r == l) printf("%d\n",p[l]); else if(r == l+1) printf("%d\n",p[r]); else { node ans; ans = query(l+2,r,1,n,1); printf("%d\n",((p[l+1]*ans.s[0][0])%MOD + (p[l]*ans.s[0][1])%MOD)%MOD); } } } return 0; }
看的宝哥的题解,这题最难在于异或,用俩延迟标记,解决的。
#include <cstdio> #include <cstring> #include <string> #include <map> using namespace std; #define N 200000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define MOD 1000000007 #define LL long long int lz[4*N],turn[4*N]; int hash[N]; void pushdown(int rt) { if(lz[rt] != -1) { lz[rt<<1] = lz[rt<<1|1] = lz[rt]; turn[rt<<1] = turn[rt<<1|1] = turn[rt]; lz[rt] = -1; turn[rt] = 0; } if(turn[rt]) { if(lz[rt<<1] != -1) lz[rt<<1] ^= 1; else turn[rt<<1] ^= 1; if(lz[rt<<1|1] != -1) lz[rt<<1|1] ^= 1; else turn[rt<<1|1] ^= 1; turn[rt] = 0; } } void update(int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { if(sc == 2) { if(lz[rt] != -1) lz[rt] ^= 1; else turn[rt] ^= 1; } else { lz[rt] = sc; turn[rt] = 0; } return ; } pushdown(rt); m = (l + r)>>1; if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); } void query(int l,int r,int rt) { int m; if(l == r) { if(lz[rt] == 1) hash[l] = 1; return ; } pushdown(rt); m = (l + r)>>1; query(lson); query(rson); } int main() { char le,ri; char ch[10]; //freopen("a.txt","r",stdin); int l,r,n,i; n = 65537*2; while(scanf("%s%*c%c%d,%d%c%*c",ch,&le,&l,&r,&ri)!=EOF) { if(le == '(') l = l*2 + 1; else l = l*2; if(ri == ')') r = r*2 - 1; else r = r*2; if(ch[0] == 'U') { update(l,r,1,0,n,1); } else if(ch[0] == 'I') { if(l-1 >= 0) update(0,l-1,0,0,n,1); update(r+1,n,0,0,n,1); } else if(ch[0] == 'D') { update(l,r,0,0,n,1); } else if(ch[0] == 'C') { if(l-1 >= 0) update(0,l-1,0,0,n,1); update(r+1,n,0,0,n,1); update(l,r,2,0,n,1); } else { update(l,r,2,0,n,1); } } query(0,n,1); int flag = 0; l = r = -1; for(i = 0;i <= n;i ++) { if(hash[i]) { if(l == -1) l = i; r = i; } else { if(l != -1) { if(flag) printf(" "); flag = 1; if(l%2) printf("(%d,",l/2); else printf("[%d,",l/2); if(r%2) printf("%d)",(r+1)/2); else printf("%d]",r/2); l = -1; } } } if(flag == 0) printf("empty set"); printf("\n"); return 0; }
挺好的一个题,不过貌似和我木啥关系。
#include <cstdio> #include <cstring> #include <string> #include <map> #include <cmath> #include <algorithm> using namespace std; #define N 300001 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define MOD 1000000007 #define LL __int64 int p[N]; int s[N]; LL sum[4*N]; int maxz[4*N]; LL lz[4*N]; int flag[N]; int o[2*N]; void pushup(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; maxz[rt] = max(maxz[rt<<1],maxz[rt<<1|1]); } void pushdown(int rt,int m) { if(lz[rt] != -1) { lz[rt<<1] = lz[rt<<1|1] = lz[rt]; sum[rt<<1] = lz[rt]*(m-(m>>1)); sum[rt<<1|1] = lz[rt]*(m>>1); maxz[rt<<1] = maxz[rt<<1|1] = lz[rt]; lz[rt] = -1; } } void build(int l,int r,int rt) { int m; if(l == r) { sum[rt] = s[l]; maxz[rt] = s[l]; return ; } m = (l + r)>>1; build(lson); build(rson); pushup(rt); } void update(int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { lz[rt] = sc; sum[rt] = sc*(r-l+1); maxz[rt] = sc; return ; } pushdown(rt,r-l+1); m = (l + r)>>1; if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); pushup(rt); } int find(int x,int l,int r,int rt) { int m; if(l == r) { if(sum[rt] > x) return l; else return l+1; } pushdown(rt,r-l+1); m = (l + r)>>1; if(x < maxz[rt<<1]) return find(x,lson); else return find(x,rson); } LL query(int L,int R,int l,int r,int rt) { LL ans = 0; if(l >= L&&r <= R) { return sum[rt]; } int m; m = (l + r)>>1; pushdown(rt,r-l+1); if(L <= m) ans += query(L,R,lson); if(R > m) ans += query(L,R,rson); return ans; } int main() { int i,n,temp,l,r; LL ans; while(scanf("%d",&n)!=EOF) { if(n == 0) break; memset(o,0,sizeof(o)); memset(lz,-1,sizeof(lz)); memset(sum,0,sizeof(sum)); for(i = 1;i <= n;i ++) { scanf("%d",&p[i]); } map<int,int> mp; for(i = n;i >= 1;i --) { if(mp.find(p[i]) != mp.end()) flag[i] = mp[p[i]]; else flag[i] = n + 1; mp[p[i]] = i; } temp = 0; ans = 0; for(i = 1;i <= n;i ++) { if(p[i] < 2*N) o[p[i]] = 1; while(o[temp]) temp ++; s[i] = temp; ans += temp; } build(1,n,1); for(i = 1;i <= n;i ++) { update(1,i,0,1,n,1); l = find(p[i],1,n,1); r = flag[i] - 1; if(l <= r) update(l,r,p[i],1,n,1); ans += query(1,n,1,n,1); } printf("%I64d\n",ans); } return 0; }
HDU 4027 Can you answer these queries?
想想,就会发现一个性质...
#include <cstdio> #include <cstring> #include <string> #include <map> #include <cmath> #include <algorithm> using namespace std; #define N 100001 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define MOD 10007 #define LL __int64 LL sum[4*N]; void pushup(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(int l,int r,int rt) { int m; if(l == r) { scanf("%I64d",&sum[rt]); return ; } m = (l + r)>>1; build(lson); build(rson); pushup(rt); } void update(int L,int R,int l,int r,int rt) { int m; if(sum[rt] == r-l+1) { return ; } if(l == r) { sum[rt] = sqrt(sum[rt]*1.0); return ; } m = (l + r)>>1; if(L <= m) update(L,R,lson); if(R > m) update(L,R,rson); pushup(rt); } LL query(int L,int R,int l,int r,int rt) { int m; LL ans = 0; if(l >= L&&r <= R) { return sum[rt]; } m = (l + r)>>1; if(L <= m) ans += query(L,R,lson); if(R > m) ans += query(L,R,rson); return ans; } int main() { int n,m,i,k,cas = 1,a,b; while(scanf("%d",&n)!=EOF) { build(1,n,1); scanf("%d",&m); printf("Case #%d:\n",cas++); for(i = 0;i < m;i ++) { scanf("%d%d%d",&k,&a,&b); if(a > b) swap(a,b); if(k == 0) { update(a,b,1,n,1); } else { printf("%I64d\n",query(a,b,1,n,1)); } } printf("\n"); } return 0; }
非常麻烦的一个题,两个lz的经典题目,各种卡常数。
#include <cstdio> #include <cstring> #include <string> #include <map> #include <cmath> #include <algorithm> using namespace std; #define N 200001 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define MOD 10007 #define LL __int64 int mul[4*N]; int add[4*N]; int sum[3][4*N]; inline int input() { int r=0; char c; c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') r=r*10+c-'0',c=getchar(); return r; } void pushup(int rt) { int i; for(i = 0; i < 3; i ++) sum[i][rt] = (sum[i][rt<<1] + sum[i][rt<<1|1])%MOD; } void fun(int rt,int tmul,int tadd,int len) { int i,ans = 0,temp; int pa[4],pm[4]; pa[0] = pm[0] = 1; for(i = 1;i < 4;i ++) { pa[i] = (pa[i-1]*tadd)%MOD; pm[i] = (pm[i-1]*tmul)%MOD; } for(i = 0; i < 3; i ++) { if(i == 0) temp = 1; else temp = 3; ans += ((((temp*pa[i])%MOD*pm[3-i])%MOD)*sum[2-i][rt])%MOD; ans %= MOD; } sum[2][rt] = (ans + len*pa[3]%MOD)%MOD; sum[1][rt] = (pm[2]*sum[1][rt])%MOD + (((2*tmul*tadd)%MOD)*sum[0][rt])%MOD + (len*pa[2])%MOD; sum[1][rt] %= MOD; sum[0][rt] = (tmul*sum[0][rt])%MOD + (len*tadd)%MOD; sum[0][rt] %= MOD; } void pushdown(int rt,int m) { if(mul[rt] != 1) { mul[rt<<1] = (mul[rt<<1]*mul[rt])%MOD; mul[rt<<1|1] = (mul[rt<<1|1]*mul[rt])%MOD; add[rt<<1] = (add[rt<<1]*mul[rt])%MOD; add[rt<<1|1] = (add[rt<<1|1]*mul[rt])%MOD; fun(rt<<1,mul[rt],0,m-(m>>1)); fun(rt<<1|1,mul[rt],0,m>>1); mul[rt] = 1; } if(add[rt] != 0) { add[rt<<1] = (add[rt<<1]+add[rt])%MOD; add[rt<<1|1] = (add[rt<<1|1]+add[rt])%MOD; fun(rt<<1,1,add[rt],m-(m>>1)); fun(rt<<1|1,1,add[rt],m>>1); add[rt] = 0; } } void build(int l,int r,int rt) { int m,i; add[rt] = 0; mul[rt] = 1; if(l == r) { for(i = 0;i < 3;i ++) sum[i][rt] = 0; return ; } m = (l + r)>>1; build(lson); build(rson); pushup(rt); } void update(int L,int R,int tmul,int tadd,int l,int r,int rt) { int m,len; if(l >= L&&r <= R) { add[rt] = (tmul*add[rt] + tadd)%MOD; mul[rt] = (tmul*mul[rt])%MOD; len = (r-l+1); fun(rt,tmul,tadd,len); return ; } m = (l + r)>>1; pushdown(rt,r-l+1); if(L <= m) update(L,R,tmul,tadd,lson); if(R > m) update(L,R,tmul,tadd,rson); pushup(rt); } int query(int L,int R,int sc,int l,int r,int rt) { int m,ans = 0; if(l >= L&&r <= R) { return sum[sc][rt]; } m = (l + r)>>1; pushdown(rt,r-l+1); if(L <= m) ans = (ans + query(L,R,sc,lson))%MOD; if(R > m) ans = (ans + query(L,R,sc,rson))%MOD; return ans; } int main() { int n,m,i,k,x,y,c; while(1) { n = input(); m = input(); if(n == 0&&m == 0) break; build(1,n,1); for(i = 0; i < m; i ++) { k = input(); x = input(); y = input(); c = input(); if(k == 1) { update(x,y,1,c,1,n,1); } else if(k == 2) { update(x,y,c,0,1,n,1); } else if(k == 3) { update(x,y,0,c,1,n,1); } else { printf("%d\n",query(x,y,c-1,1,n,1)); } } } return 0; }
本来是应该1Y的题目,结果一个i写成了rt,让我一直RE,我盲cha了半天,没检查出错...哎呀,我不能忍啊....
这题思路就是标记最大连续的,左边,右边,延迟。
#include <cstdio> #include <cstring> #include <string> #include <map> #include <cmath> #include <algorithm> using namespace std; #define N 101000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int lbd[2][4*N],rbd[2][4*N]; int maxz[2][4*N],lz[2][4*N]; void pushup(int i,int rt,int m) { maxz[i][rt] = max(maxz[i][rt<<1],maxz[i][rt<<1|1]); maxz[i][rt] = max(maxz[i][rt],rbd[i][rt<<1] + lbd[i][rt<<1|1]); if(lbd[i][rt<<1] == m - (m>>1)) lbd[i][rt] = lbd[i][rt<<1] + lbd[i][rt<<1|1]; else lbd[i][rt] = lbd[i][rt<<1]; if(rbd[i][rt<<1|1] == m>>1) rbd[i][rt] = rbd[i][rt<<1|1] + rbd[i][rt<<1]; else rbd[i][rt] = rbd[i][rt<<1|1]; } void pushdown(int i,int rt,int m) { if(lz[i][rt] != -1) { lz[i][rt<<1] = lz[i][rt<<1|1] = lz[i][rt]; maxz[i][rt<<1] = (m-(m>>1))*lz[i][rt]; maxz[i][rt<<1|1] = (m>>1)*lz[i][rt]; lbd[i][rt<<1] = (m-(m>>1))*lz[i][rt]; lbd[i][rt<<1|1] = (m>>1)*lz[i][rt]; rbd[i][rt<<1] = (m-(m>>1))*lz[i][rt]; rbd[i][rt<<1|1] = (m>>1)*lz[i][rt]; lz[i][rt] = -1; } } void build(int l,int r,int rt) { int m,i; lz[0][rt] = -1; lz[1][rt] = -1; if(l == r) { for(i = 0;i < 2;i ++) { lbd[i][rt] = 1; rbd[i][rt] = 1; maxz[i][rt] = 1; } return ; } m = (l + r)>>1; build(lson); build(rson); for(i = 0;i < 2;i ++) pushup(i,rt,r-l+1); } void update(int i,int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { maxz[i][rt] = sc*(r-l+1); lbd[i][rt] = sc*(r-l+1); rbd[i][rt] = sc*(r-l+1); lz[i][rt] = sc; return ; } m = (l + r)>>1; pushdown(i,rt,r-l+1); if(L <= m) update(i,L,R,sc,lson); if(R > m) update(i,L,R,sc,rson); pushup(i,rt,r-l+1); } int find(int i,int x,int l,int r,int rt) { int m = (l + r)>>1; pushdown(i,rt,r-l+1); if(maxz[i][rt] < x) return -1; if(l == r) { return l; } if(maxz[i][rt<<1] >= x) { return find(i,x,lson); } else if(rbd[i][rt<<1] + lbd[i][rt<<1|1] >= x) { return m - rbd[i][rt<<1] + 1; } return find(i,x,rson); } int main() { int t,n,m,cas = 1,temp,i,a,b; char str[1001]; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); build(1,n,1); printf("Case %d:\n",cas++); for(i = 0;i < m;i ++) { scanf("%s",str); if(str[0] == 'D') { scanf("%d",&a); temp = find(0,a,1,n,1); if(temp > 0) { update(0,temp,temp+a-1,0,1,n,1); printf("%d,let's fly\n",temp); } else { printf("fly with yourself\n"); } } else if(str[0] == 'N') { scanf("%d",&a); temp = find(0,a,1,n,1); if(temp > 0) { update(0,temp,temp+a-1,0,1,n,1); update(1,temp,temp+a-1,0,1,n,1); printf("%d,don't put my gezi\n",temp); continue; } temp = find(1,a,1,n,1); if(temp > 0) { update(0,temp,temp+a-1,0,1,n,1); update(1,temp,temp+a-1,0,1,n,1); printf("%d,don't put my gezi\n",temp); continue; } printf("wait for me\n"); } else { scanf("%d%d",&a,&b); update(0,a,b,1,1,n,1); update(1,a,b,1,1,n,1); printf("I am the hope of chinese chengxuyuan!!\n"); } } } return 0; }
耐下心来想想,就应该想出来了。不是延迟,就是标记什么的。难得的1Y。
#include <cstdio> #include <cstring> #include <string> #include <map> #include <cmath> #include <algorithm> #include <queue> using namespace std; #define LL __int64 #define N 100100 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int que[200001]; LL sum[5][4*N]; int flag[4*N]; int q1[N]; int q2[N]; int bin(int x,int n) { int str,end,mid; str = 0; end = n; while(str <= end) { mid = (str + end)/2; if(que[mid] == x) return mid; else if(que[mid] > x) end = mid - 1; else str = mid + 1; } return mid; } void pushup(int rt) { int i,x; x = flag[rt<<1]; flag[rt] = (flag[rt<<1] + flag[rt<<1|1]) % 5; for(i = 0;i < 5;i ++) { sum[(i+x)%5][rt] = sum[(i+x)%5][rt<<1] + sum[i][rt<<1|1]; } } void update(int x,int sc,int l,int r,int rt) { int m; if(l == r) { flag[rt] += sc; if(sc == 1) sum[1][rt] = que[x]; else sum[1][rt] = 0; return ; } m = (l + r)>>1; if(x <= m) update(x,sc,lson); else update(x,sc,rson); pushup(rt); } int main() { int n,i,k,m; char str[10]; while(scanf("%d",&n)!=EOF) { m = 0; memset(flag,0,sizeof(flag)); memset(sum,0,sizeof(sum)); for(i = 0;i < n;i ++) { scanf("%s",str); if(str[0] == 'a') { scanf("%d",&q2[i]); que[m++] = q2[i]; q1[i] = 1; } else if(str[0] == 'd') { scanf("%d",&q2[i]); q1[i] = 2; } else { q1[i] = 3; } } sort(que,que+m); k = 1; for(i = 1;i < m;i ++) { if(que[i] != que[i-1]) que[k++] = que[i]; } for(i = 0;i < n;i ++) { if(q1[i] == 1) { int pos = bin(q2[i],k-1); update(pos,1,0,k-1,1); } else if(q1[i] == 2) { int pos = bin(q2[i],k-1); update(pos,-1,0,k-1,1); } else { printf("%I64d\n",sum[3][1]); } } } return 0; }
SGU 311 Ice-cream Tycoon
这题写起来比较麻烦,恰好可以进行一个成段染色,并且不影响sum...sum存价格的和,p存数量的和,单点更新+成段更新+离散化,不离散化会MLE。错的飞起,错了很多次。
#include <cstdio> #include <cstring> #include <string> #include <map> #include <cmath> #include <algorithm> using namespace std; #define LL __int64 #define N 201000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 LL sum[4*N]; LL p[4*N]; int lz[4*N]; LL que[N]; LL q[3][N]; void pushup(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; p[rt] = p[rt<<1] + p[rt<<1|1]; } void pushdown(int rt,int m) { if(lz[rt]) { lz[rt<<1] = lz[rt<<1|1] = lz[rt]; sum[rt<<1] = sum[rt<<1|1] = 0; p[rt<<1] = p[rt<<1|1] = 0; lz[rt] = 0; } } void update(int x,int sc,int l,int r,int rt) { int m; if(l == r) { p[rt] += sc; sum[rt] += (LL)sc*que[l]; return ; } m = (l + r)>>1; pushdown(rt,r-l+1); if(x <= m) update(x,sc,lson); else update(x,sc,rson); pushup(rt); } void update(int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { lz[rt] = sc; sum[rt] = 0; p[rt] = 0; return ; } m = (l + r)>>1; pushdown(rt,r-l+1); if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); pushup(rt); } LL query1(int L,int R,int l,int r,int rt) { int m; LL ans = 0; if(l >= L&&r <= R) { return p[rt]; } m = (l + r)>>1; pushdown(rt,r-l+1); if(L <= m) ans += query1(L,R,lson); if(R > m) ans += query1(L,R,rson); return ans; } LL query2(int L,int R,int l,int r,int rt) { int m; LL ans = 0; if(l >= L&&r <= R) { return sum[rt]; } m = (l + r)>>1; pushdown(rt,r-l+1); if(L <= m) ans += query2(L,R,lson); if(R > m) ans += query2(L,R,rson); return ans; } int find(LL x,int l,int r,int rt) { int m; m = (l + r)>>1; pushdown(rt,r-l+1); if(l == r) return l; if(p[rt<<1] >= x) return find(x,lson); return find(x-p[rt<<1],rson); } int bin(int x,int n) { int str,mid,end; str = 1; end = n; while(str <= end) { mid = (str + end)/2; if(que[mid] == x) return mid; else if(que[mid] > x) end = mid - 1; else str = mid + 1; } return mid; } int main() { char str[100]; int n,temp,m,k,i; LL num,st,a,b; k = 1; m = 0; while(scanf("%s",str)!=EOF) { scanf("%I64d%I64d",&a,&b); if(str[0] == 'A') { q[0][m] = 0; que[k++] = b; } else q[0][m] = 1; q[1][m] = a; q[2][m] = b; m ++; } sort(que+1,que+k); n = 2; for(i = 2;i < k;i ++) { if(que[i] != que[i-1]) que[n++] = que[i]; } n --; for(i = 0;i < m;i ++) { if(q[0][i] == 0) { a = q[1][i]; b = bin(q[2][i],n); update(b,a,1,n,1); } else { a = q[1][i]; b = q[2][i]; if(p[1] < a) printf("UNHAPPY\n"); else { temp = find(a,1,n,1); num = 0; st = 0; if(temp-1 >= 1) { num = query1(1,temp-1,1,n,1); st = query2(1,temp-1,1,n,1); } if((a-num)*que[temp] + st > b) printf("UNHAPPY\n"); else { if(temp-1 >= 1) update(1,temp-1,1,1,n,1); update(temp,-(a-num),1,n,1); printf("HAPPY\n"); } } } } return 0; }
做过,同类型的,但是其实并不理解,sum[0]表示只有1个矩形覆盖,sum[1]表示2个以上覆盖。如果cnt[1] = 1,此段sum[1] = 左sum[1] + 右sum[1] + 左sum[0] + 右sum[0]。利用这个就能做出来了。
#include <cstdio> #include <cstring> #include <string> #include <map> #include <cmath> #include <vector> #include <algorithm> using namespace std; #define LL long long #define N 10001 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node { double lx,rx,y; int s; node(){} node(double a,double b,double c,int d):lx(a),rx(b),y(c),s(d){} bool operator < (const node &S)const { return y < S.y; } }mat[N]; double sum[2][4*N]; int cnt[4*N]; double que[N]; int bin(double x,int n) { int str,end,mid; str = 0; end = n; while(str <= end) { mid = (str + end)/2; if(que[mid] == x) return mid; else if(que[mid] > x) end = mid - 1; else str = mid + 1; } return mid; } void pushup(int rt,int l,int r) { if(cnt[rt] == 1) { sum[1][rt] = sum[0][rt<<1] + sum[0][rt<<1|1] + sum[1][rt<<1] + sum[1][rt<<1|1]; sum[0][rt] = que[r+1] - que[l] - sum[1][rt]; } else if(cnt[rt] > 1) { sum[1][rt] = que[r+1] - que[l]; sum[0][rt] = 0; } else if(l == r) { sum[0][rt] = sum[1][rt] = 0; } else { sum[0][rt] = sum[0][rt<<1] + sum[0][rt<<1|1]; sum[1][rt] = sum[1][rt<<1] + sum[1][rt<<1|1]; } } void update(int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { cnt[rt] += sc; pushup(rt,l,r); return ; } m = (l + r)>>1; if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); pushup(rt,l,r); } int main() { int t,i,n,m,k,l,r; double x1,y1,x2,y2; scanf("%d",&t); while(t--) { scanf("%d",&n); m = 0; for(i = 0;i < n;i ++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); que[m] = x1; mat[m++] = node(x1,x2,y1,1); que[m] = x2; mat[m++] = node(x1,x2,y2,-1); } sort(que,que+m); sort(mat,mat+m); k = 1; for(i = 1;i < m;i ++) { if(que[i] != que[i-1]) que[k++] = que[i]; } memset(cnt,0,sizeof(cnt)); memset(sum,0,sizeof(sum)); double ans = 0.0; for(i = 0;i < m-1;i ++) { l = bin(mat[i].lx,k-1); r = bin(mat[i].rx,k-1)-1; if(l <= r) update(l,r,mat[i].s,0,k-1,1); ans += sum[1][1]*(mat[i+1].y-mat[i].y); } printf("%.2lf\n",ans); } return 0; }
三维立方体,求三个及以上的体积并,注意int64,wa了几次,思路跟面积并什么的差不多。
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; #define N 3001 #define LL __int64 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct point { int x,y,z; }p[2001]; LL sum[3][4*N]; int cnt[4*N]; int zi[N]; int que[N]; struct node { int lx,rx,y,s; node(){} node(int a,int b,int c,int d):lx(a),rx(b),y(c),s(d){} bool operator < (const node &S)const { return y < S.y; } }mat[N]; int bin(int x,int n) { int str,end,mid; str = 0; end = n; while(str <= end) { mid = (str + end)/2; if(que[mid] == x) return mid; else if(que[mid] > x) end = mid - 1; else str = mid + 1; } return mid; } void pushup(int rt,int l,int r) { int i; if(cnt[rt] >= 3) { sum[2][rt] = que[r+1] - que[l]; sum[1][rt] = 0; sum[0][rt] = 0; } else if(cnt[rt] == 2) { sum[2][rt] = 0; for(i = 0;i < 3;i ++) sum[2][rt] += sum[i][rt<<1] + sum[i][rt<<1|1]; sum[1][rt] = que[r+1] - que[l] - sum[2][rt]; sum[0][rt] = 0; } else if(cnt[rt] == 1) { sum[2][rt] = sum[2][rt<<1] + sum[2][rt<<1|1] + sum[1][rt<<1] + sum[1][rt<<1|1]; sum[1][rt] = sum[0][rt<<1] + sum[0][rt<<1|1]; sum[0][rt] = que[r+1] - que[l] - sum[2][rt] - sum[1][rt]; } else if(l == r) { sum[0][rt] = sum[1][rt] = sum[2][rt] = 0; } else { for(i = 0;i < 3;i ++) sum[i][rt] = sum[i][rt<<1] + sum[i][rt<<1|1]; } } void update(int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { cnt[rt] += sc; pushup(rt,l,r); return ; } m = (l + r)>>1; if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); pushup(rt,l,r); } LL fun(int n) { int i,k,l,r; LL ans; k = 1; for(i = 1;i < n;i ++) { if(que[i] != que[i-1]) que[k++] = que[i]; } memset(sum,0,sizeof(sum)); memset(cnt,0,sizeof(cnt)); ans = 0; for(i = 0;i < n-1;i ++) { l = bin(mat[i].lx,k-1); r = bin(mat[i].rx,k-1)-1; if(l <= r) update(l,r,mat[i].s,0,k-1,1); ans += (LL)sum[2][1]*(mat[i+1].y-mat[i].y); } return ans; } int main() { int t,cas = 1,n,i,j,k,num; LL ans; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i = 0;i < 2*n;i ++) { scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z); zi[i] = p[i].z; } sort(zi,zi+2*n); k = 1; for(i = 1;i < 2*n;i ++) { if(zi[i] != zi[i-1]) zi[k++] = zi[i]; } ans = 0; for(i = 0;i < k-1;i ++) { num = 0; for(j = 0;j < n;j ++) { if(zi[i] >= p[j*2].z&&zi[i] < p[j*2+1].z) { que[num] = p[j*2].x; mat[num++] = node(p[j*2].x,p[j*2+1].x,p[j*2].y,1); que[num] = p[j*2+1].x; mat[num++] = node(p[j*2].x,p[j*2+1].x,p[j*2+1].y,-1); } } sort(que,que+num); sort(mat,mat+num); ans += (LL)fun(num)*(zi[i+1]-zi[i]); } printf("Case %d: %I64d\n",cas++,ans); } return 0; }
SGU Kalevich Strikes Back 这个题,很特别。扫描线的时候如果下边发生覆盖,这次的线段肯定比上次的要短,所以每个矩形都有一个pre,pre的矩形-当前矩形的面积就行了,可是我写的一直有问题,看了看别人的+了一个pushup函数就过了,更新那里还是有点问题啊....
#include <cstdio> #include <cstring> #include <string> #include <map> #include <cmath> #include <algorithm> #include <queue> using namespace std; #define LL long long #define N 220100 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node { int lx,rx,y,s,id; node() {} node(int a,int b,int c,int d,int t):lx(a),rx(b),y(c),s(d),id(t) {} bool operator < (const node &S)const { return y < S.y; } } mat[N]; int lz[4*N]; int que[N]; int pre[N]; int flag[N]; LL ans[N]; int bin(int x,int n) { int str,mid,end; str = 0; end = n; while(str <= end) { mid = (str + end)/2; if(que[mid] == x) return mid; else if(que[mid] > x) end = mid - 1; else str = mid + 1; } return mid; } void pushdown(int rt) { if(lz[rt]) { lz[rt<<1] = lz[rt<<1|1] = lz[rt]; lz[rt] = 0; } } void pushup(int rt) { if(lz[rt<<1] == lz[rt<<1|1]&&lz[rt<<1]) { lz[rt] = lz[rt<<1]; lz[rt<<1] = lz[rt<<1|1] = 0; } } void update(int L,int R,int sc,int l,int r,int rt) { int m; if(l >= L&&r <= R) { if(sc < 0) { lz[rt] = pre[-sc]; } else { if(flag[sc] == 0&&lz[rt]) { pre[sc] = lz[rt]; flag[sc] = 1; ans[lz[rt]] -= ans[sc]; } lz[rt] = sc; } return ; } pushdown(rt); m = (l + r) >> 1; if(L <= m) update(L,R,sc,lson); if(R > m) update(L,R,sc,rson); pushup(rt); } int main() { int i,k,n,m,x1,x2,y1,y2,w,h,num; scanf("%d",&n); m = 0; num = 1; scanf("%d%d",&w,&h); x1 = w; y1 = 0; x2 = 0; y2 = h; que[m] = x1; ans[num++] = ((LL)x1-x2)*((LL)y2-y1); mat[m++] = node(x2,x1,y1,1,num-1); que[m] = x2; mat[m++] = node(x2,x1,y2,-1,num-1); for(i = 0; i < n; i ++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x2 > x1) swap(x2,x1); if(y1 > y2) swap(y1,y2); que[m] = x1; ans[num++] = ((LL)x1-x2)*((LL)y2-y1); mat[m++] = node(x2,x1,y1,1,num-1); que[m] = x2; mat[m++] = node(x2,x1,y2,-1,num-1); } sort(que,que+m); sort(mat,mat+m); k = 1; for(i = 1; i < m; i ++) { if(que[i] != que[i-1]) que[k++] = que[i]; } memset(lz,0,sizeof(lz)); memset(pre,0,sizeof(pre)); int l,r; for(i = 0; i < m-1; i ++) { l = bin(mat[i].lx,k-1); r = bin(mat[i].rx,k-1)-1; if(l <= r) { if(mat[i].s > 0) update(l,r,mat[i].id,0,k-1,1); else update(l,r,-mat[i].id,0,k-1,1); } } sort(ans,ans+num); for(i = 1; i < num; i ++) { if(i != 1) printf(" "); printf("%lld",ans[i]); } printf("\n"); return 0; } /* 4 7 7 1 1 2 2 1 3 4 4 3 1 4 2 5 1 6 6 */