迷之查做题?!

于是我就被教练迷之查了一发做题进度。
虽然无力吐槽,然而我还是把这几道题都写(水)了。
查到我的题目是:BZOJ3529,BZOJ2243,BZOJ3065。
然而我一开始只写了BZOJ3529......

BZOJ3529:
先反演然后树状数组,对于每个值的f用nlog筛即可。
代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define debug cout
  6 using namespace std;
  7 const int maxn=1e5+1e2;
  8 const int mod=0x7fffffff;
  9  
 10 struct BinaryIndexTree {
 11     int dat[maxn];
 12     #define lowbit(x) ( x & -x )
 13     inline void update(int pos,int x) {
 14         while( pos < maxn )
 15             dat[pos] += x,
 16             pos += lowbit(pos);
 17     }
 18     inline int query(int pos) {
 19         int ret = 0;
 20         while( pos )
 21             ret += dat[pos],
 22             pos -= lowbit(pos);
 23         return ret;
 24     }
 25 }bit;
 26  
 27 struct QNode {
 28     int n,m,a,id;
 29     friend bool operator < (const QNode &a,const QNode &b) {
 30         return a.a < b.a;
 31     }
 32 }ns[maxn];
 33 struct FNode {
 34     int f,div;
 35     friend bool operator < (const FNode &a,const FNode &b) {
 36         return a.f < b.f;
 37     }
 38 }fs[maxn];
 39  
 40 int mu[maxn];
 41 int ans[maxn],n,m,t;
 42  
 43 inline void pre() {
 44     static int prime[maxn],cnt;
 45     static char vis[maxn];
 46     mu[1] = 1;
 47     for(int i=2;i<maxn;i++) {
 48         if( !vis[i] )
 49             prime[++cnt] = i,
 50             mu[i] = -1;
 51         for(int j=1;j<=cnt&&i*prime[j]<maxn;j++) {
 52             vis[i*prime[j]] = 1,
 53             mu[i*prime[j]] = -mu[i];
 54             if( ! ( i % prime[j] ) ) {
 55                 mu[i*prime[j]] = 0;
 56                 break;
 57             }
 58         }
 59     }
 60     for(int i=1;i<maxn;i++) {
 61         fs[i].div = i;
 62         for(int j=i;j<maxn;j+=i)
 63             fs[j].f += i;
 64     }
 65 }
 66  
 67 inline int calc(int n,int m) {
 68     int ret = 0 , lim = min(n,m);
 69     for(int i=1,j;i<=lim;i=j+1) {
 70         j = min( n / ( n / i ) , m / ( m / i ) );
 71         ret += ( n / i ) * ( m / i ) * ( bit.query(j) - bit.query(i-1) );
 72     }
 73     return ret & mod;
 74 }
 75  
 76 inline void getans() {
 77     sort(ns+1,ns+1+n);
 78     sort(fs+1,fs+maxn);
 79     int pos = 0;
 80     for(int i=1;i<=n;i++) {
 81         while( pos + 1 < maxn && fs[pos+1].f <= ns[i].a ) {
 82             ++pos;
 83             for(int j=fs[pos].div;j<maxn;j+=fs[pos].div)
 84                 bit.update(j,fs[pos].f*mu[j/fs[pos].div]);
 85         }
 86         ans[ns[i].id] = calc(ns[i].n,ns[i].m);
 87     }
 88 }
 89  
 90 int main() {
 91     scanf("%d",&n);
 92     for(int i=1;i<=n;i++)
 93         scanf("%d%d%d",&ns[i].n,&ns[i].m,&ns[i].a),
 94         ns[i].id = i;
 95     pre();
 96     getans();
 97      
 98     for(int i=1;i<=n;i++)
 99         printf("%d\n",ans[i]);
100      
101     return 0;
102 }
View Code


BZOJ2243:
树链剖分线段树维护节点颜色,具体就是维护两边颜色和中间颜色个数。
写一个Node类就好做多了。讲真的不明白他们代码为什么都写那么长QAQ。
记得链合并时一边需要reverse(因为我的线段树从左向右都是从上到下)。
对于lca为a或b的需要特判,或者通过两次判定deep省去特判。详见代码。
(分类讨论什么的,自己纸上画一画就明白了)
另外一开始query的时候没写push给WA了一回。
代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define debug cout
  6 using namespace std;
  7 const int maxn=1e5+1e2;
  8  
  9 int s[maxn],t[maxn<<1],nxt[maxn<<1];
 10 int fa[maxn],dep[maxn],top[maxn],son[maxn],siz[maxn],id[maxn],cov[maxn];
 11 int in[maxn],bin[maxn];
 12 int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3],lazy[maxn<<3],cnt;
 13 int n,m;
 14  
 15 struct Node {
 16     int cl,cr,sum;
 17     friend Node operator + (const Node &a,const Node &b) {
 18         return (Node){a.cl,b.cr,a.sum+b.sum-(a.cr==b.cl)};
 19     }
 20     inline void fill(int c) {
 21         cl = cr = c , sum = 1;
 22     }
 23     inline Node reverse() {
 24         return (Node){cr,cl,sum};
 25     }
 26 }ns[maxn<<3];
 27  
 28 inline void build(int pos,int ll,int rr) {
 29     l[pos] = ll , r[pos] = rr;
 30     if( ll == rr ) {
 31         ns[pos].fill(bin[ll]);
 32         return;
 33     }
 34     const int mid = ( ll + rr ) >> 1;
 35     build(lson[pos]=++cnt,ll,mid);
 36     build(rson[pos]=++cnt,mid+1,rr);
 37     ns[pos] = ns[lson[pos]] + ns[rson[pos]];
 38 }
 39 inline void push(int pos) {
 40     if( lazy[pos] ) {
 41         if( lson[pos] ) {
 42             ns[lson[pos]].fill(lazy[pos]);
 43             lazy[lson[pos]] = lazy[pos];
 44         }
 45         if( rson[pos] ) {
 46             ns[rson[pos]].fill(lazy[pos]);
 47             lazy[rson[pos]] = lazy[pos];
 48         }
 49         lazy[pos] = 0;
 50     }
 51 }
 52 inline void update(int pos,int ll,int rr,int cc) {
 53     if( rr < l[pos] || r[pos] < ll )
 54         return;
 55     if( ll <= l[pos] && r[pos] <= rr ) {
 56         ns[pos].fill(lazy[pos]=cc);
 57         return;
 58     }
 59     push(pos);
 60     update(lson[pos],ll,rr,cc);
 61     update(rson[pos],ll,rr,cc);
 62     ns[pos] = ns[lson[pos]] + ns[rson[pos]];
 63 }
 64 inline Node query(int pos,int ll,int rr) {
 65     if( ll <= l[pos] && r[pos] <= rr )
 66         return ns[pos];
 67     const int mid = ( l[pos] + r[pos] ) >> 1;
 68     push(pos);
 69     if( rr <= mid )
 70         return query(lson[pos],ll,rr);
 71     else if( ll > mid )
 72         return query(rson[pos],ll,rr);
 73     return query(lson[pos],ll,rr) + query(rson[pos],ll,rr);
 74 }
 75  
 76 inline void addedge(int from,int to) {
 77     static int cnt = 0;
 78     t[++cnt] = to ,
 79     nxt[cnt] = s[from] , s[from] = cnt;
 80 }
 81 inline void pre(int pos) {
 82     siz[pos] = 1;
 83     for(int at=s[pos];at;at=nxt[at])
 84         if( t[at] != fa[pos] ) {
 85             dep[t[at]] = dep[pos] + 1,
 86             fa[t[at]] = pos;
 87             pre(t[at]);
 88             siz[pos] += siz[t[at]];
 89             if( siz[t[at]] > siz[son[pos]] )
 90                 son[pos] = t[at];
 91         }
 92 }
 93 inline void dfs(int pos) {
 94     top[pos] = son[fa[pos]] == pos ? top[fa[pos]] : pos;
 95     id[pos] = top[pos] == top[fa[pos]] ? id[fa[pos]] + 1 : 1;
 96     for(int at=s[pos];at;at=nxt[at])
 97         if( t[at] != fa[pos] )
 98             dfs(t[at]);
 99     if( !son[pos] ) {
100         for(int p=pos;;p=fa[p]) {
101             bin[id[p]] = in[p];
102             if( p == top[pos] )
103                 break;
104         }
105         cov[top[pos]] = ++cnt;
106         build(cov[top[pos]],id[top[pos]],id[pos]);
107     }
108 }
109 inline void chain(int a,int b,int cc) {
110     while( top[a] != top[b] ) {
111         if( dep[top[a]] > dep[top[b]] ) {
112             update(cov[top[a]],id[top[a]],id[a],cc);
113             a = fa[top[a]];
114         }
115         else {
116             update(cov[top[b]],id[top[b]],id[b],cc);
117             b = fa[top[b]];
118         }
119     }
120     if( dep[a] > dep[b] )
121         swap(a,b);
122     update(cov[top[a]],id[a],id[b],cc);
123 }
124 inline Node getans(int a,int b) {
125     if( dep[a] > dep[b] )
126         swap(a,b);
127     Node qa = query(cov[top[a]],id[a],id[a]) , qb = query(cov[top[b]],id[b],id[b]);
128     while( top[a] != top[b] ) {
129         if( !( a && b ) )
130             exit(0);
131         if( dep[top[a]] > dep[top[b]] ) {
132             qa = query(cov[top[a]],id[top[a]],id[a]) + qa;
133             a = fa[top[a]];
134         }
135         else {
136             qb = query(cov[top[b]],id[top[b]],id[b]) + qb;
137             b = fa[top[b]];
138         }
139     }
140     if( dep[a] > dep[b] )
141         swap(a,b) ,
142         swap(qa,qb);
143     qb = query(cov[top[a]],id[a],id[b]) + qb;
144     qa = qa.reverse() + qb;
145     return qa;
146 }
147  
148 int main() {
149     static char com[10];
150     scanf("%d%d",&n,&m);
151     for(int i=1;i<=n;i++)
152         scanf("%d",in+i);
153     for(int i=1,a,b;i<n;i++) {
154         scanf("%d%d",&a,&b);
155         addedge(a,b) , addedge(b,a);
156     }
157     pre(1);
158     dfs(1);
159     for(int i=1,a,b,cc;i<=m;i++) {
160         scanf("%s%d%d",com,&a,&b);
161         if( *com == 'C' ) {
162             scanf("%d",&cc);
163             chain(a,b,cc);
164         }
165         else {
166             Node ans = getans(a,b);
167             printf("%d\n",ans.sum);
168         }
169     }
170      
171     return 0;
172 }
View Code


BZOJ3065:
带插入修改区间k小值?
平衡树套主席树?
对不起,我只会分块,分块大法好。直接进前20。


代码:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #define debug cout
  4 using namespace std;
  5 const int maxs=130,maxb=1220,blk=600;
  6  
  7 int sou[maxs][maxb],rt[maxs][maxb],nxt[maxs],siz[maxs],sc;
  8 int n,m,lastp,used,lastans;
  9  
 10 inline void cpy(int* dst,int *sou,int len) {
 11     int ite = ( len + 7 ) >> 3;
 12     switch( len & 7 ) {
 13         case 0: do{ *dst++ = *sou++;
 14         case 1: *dst++ = *sou++;
 15         case 2: *dst++ = *sou++;
 16         case 3: *dst++ = *sou++;
 17         case 4: *dst++ = *sou++;
 18         case 5: *dst++ = *sou++;
 19         case 6: *dst++ = *sou++;
 20         case 7: *dst++ = *sou++; }while(ite--);
 21     }
 22 }
 23  
 24 inline void reb(int id) {
 25     cpy(rt[id]+1,sou[id]+1,siz[id]);
 26     sort(rt[id]+1,rt[id]+1+siz[id]);
 27 }
 28  
 29 inline void getp(int k,int& rb,int& rk) {
 30     rb = 1 , rk = k;
 31     while( rk > siz[rb] && nxt[rb] ) {
 32         rk -= siz[rb] , 
 33         rb = nxt[rb];
 34     }
 35 }
 36  
 37 inline int bin(int id,int k) { // returning the number of elements which < k in block id.
 38     return lower_bound(rt[id]+1,rt[id]+1+siz[id],k) - rt[id] - 1;
 39 }
 40 inline int cont(int id,int l,int r,int k) { // returning the number of elements which < k in block id's range[l,r].
 41     int ret = 0;
 42     for(int i=l;i<=r;i++)
 43         ret += ( sou[id][i] < k );
 44     return ret;
 45 }
 46  
 47 inline int kth(int l,int r,int k) {
 48     int lb,lpp,rb,rpp;
 49     getp(l,lb,lpp) , getp(r,rb,rpp);
 50     int ll = -1 , rr = 70001 , mid , lam;
 51     while( rr > ll + 1 ) {
 52         mid = ( ll + rr ) >> 1 , lam = 0;
 53         if( lb == rb )
 54             lam = cont(lb,lpp,rpp,mid);
 55         else {
 56             lam = cont(lb,lpp,siz[lb],mid) + cont(rb,1,rpp,mid);
 57             for(int pos=nxt[lb];pos!=rb;pos=nxt[pos])
 58                 lam += bin(pos,mid);
 59         }
 60         if( lam < k )
 61             ll = mid;
 62         else
 63             rr = mid;
 64     }
 65     return ll;
 66 }
 67 inline void upd(int tar,int nv) {
 68     int b,pp;
 69     getp(tar,b,pp);
 70     int i;
 71     for(i=1;rt[b][i]!=sou[b][pp];i++) ;
 72     sou[b][pp] = rt[b][i] = nv;
 73     while( i < siz[b] && rt[b][i] > rt[b][i+1] )
 74         swap(rt[b][i],rt[b][i+1]) , ++i;
 75     while( i > 1 && rt[b][i] < rt[b][i-1] )
 76         swap(rt[b][i],rt[b][i-1]) , --i;
 77 }
 78 inline void ins(int tar,int nv) {
 79     int b,pp;
 80     getp(tar,b,pp);
 81     for(int i=siz[b]+1;i>pp;i--)
 82         sou[b][i] = sou[b][i-1];
 83     rt[b][++siz[b]] = sou[b][pp] = nv;
 84     for(int i=siz[b]; i > 1 && rt[b][i] < rt[b][i-1] ;i--)
 85         swap(rt[b][i],rt[b][i-1]);
 86     if( siz[b] >= ( blk << 1 ) ) {
 87         nxt[++sc] = nxt[b] ,
 88         nxt[b] = sc;
 89         for(int i=1;i<=blk;i++)
 90             sou[sc][i] = sou[b][i+blk] ,
 91             sou[b][i+blk] = rt[b][i+blk] = 0;
 92         siz[b] = siz[sc] = blk;
 93         reb(b) , reb(sc);
 94     }
 95 }
 96  
 97 int main() {
 98     static char com[10];
 99     scanf("%d",&n);
100     for(int i=1;i<=n;i++) {
101         if( used < i ) {
102             lastp = used , used = min( used + blk , n );
103             siz[++sc] = used - lastp;
104             if( sc != 1 )
105                 nxt[sc-1] = sc;
106         }
107         scanf("%d",&sou[sc][i-lastp]);
108     }
109     for(int i=1;i<=sc;i++)
110         reb(i);
111     scanf("%d",&m);
112     for(int i=1,l,r,k,u,p;i<=m;i++) {
113         scanf("%s",com);
114         if( *com == 'I' ) {
115             scanf("%d%d",&p,&u);
116             p ^= lastans , u ^= lastans;
117             ins(p,u);
118         }
119         else if( *com == 'M' ) {
120             scanf("%d%d",&p,&u);
121             p ^= lastans , u ^= lastans;
122             upd(p,u);
123         }
124         else if( *com == 'Q' ) {
125             scanf("%d%d%d",&l,&r,&k);
126             l ^= lastans , r ^= lastans , k ^= lastans;
127             printf("%d\n",lastans=kth(l,r,k));
128         }
129     }
130     return 0;
131 }
View Code

 

posted @ 2018-01-09 21:56  Cmd2001  阅读(219)  评论(0编辑  收藏  举报