北京集训:20180325

你说我怎么这么菜呢?

T1:


考场上没看到下取整,同时把那个sigma看成了次数,以为要在mod phi(p)下算,这玩意能做?
然后果断爆零......
其实puts(2的逆元)+puts("1")有25分......
正解看官方题解吧。


那个鬼畜的容斥大概就是在n+1个断点中钦定k个断点,数字相对于剩下的m+1-k个集合的位置无关,所以对于这m+1-k个集合可以随意放置。
代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 typedef long long int lli;
 4 const int maxn=1e5+1e2,maxl=262145;
 5 const int mod=998244353,g=3;
 6 
 7 lli fac[maxn],inv[maxn];
 8 lli lft[maxl],rit[maxl],tar[maxl];
 9 lli ans;
10 int n,m;
11 
12 inline lli fastpow(lli base,int tim) {
13     lli ret = 1;
14     while( tim ) {
15         if( tim & 1 ) ret = ret * base % mod;
16         if( tim >>= 1 ) base = base * base % mod;
17     }
18     return ret;
19 }
20 inline void NTT(lli* dst,int n,int ope=1) {
21     for(int i=0,j=0;i<n;i++) {
22         if( i < j ) std::swap(dst[i],dst[j]);
23         for(int t=n>>1;(j^=t)<t;t>>=1);
24     }
25     for(int len=2;len<=n;len<<=1) {
26         const int h = len >> 1;
27         lli per = fastpow(g,mod/len);
28         if( !~ope ) per = fastpow(per,mod-2);
29         for(int st=0;st<n;st+=len) {
30             lli w = 1;
31             for(int pos=0;pos<h;pos++) {
32                 const lli u = dst[st+pos] , v = dst[st+pos+h] * w % mod;
33                 dst[st+pos] = ( u + v ) % mod ,
34                 dst[st+pos+h] = ( u - v + mod ) % mod ,
35                 w = w * per % mod;
36             }
37         }
38     }
39     if( !~ope ) {
40         const lli inv = fastpow(n,mod-2);
41         for(int i=0;i<n;i++) dst[i] = dst[i] * inv % mod;
42     }
43 }
44 
45 inline lli c(int n,int m) {
46     return fac[n] * inv[m] % mod * inv[n-m] % mod;
47 }
48 inline void init() {
49     for(int i=0;i<=n+1;i++) {
50         lft[i] = ( i & 1 ) ? mod - c(n+1,i) : c(n+1,i);
51         rit[i] = fastpow(i,n);
52     }
53 }
54 inline void getans() {
55     init(); int len = 1;
56     while( len <= ( n << 1 ) + 1 ) len <<= 1;
57     NTT(lft,len) , NTT(rit,len);
58     for(int i=0;i<len;i++) tar[i] = lft[i] * rit[i] % mod;
59     NTT(tar,len,-1);
60     for(int i=0;i<=n;i++) ans = ( ans + tar[i+1] * fastpow(i,m) % mod ) % mod;
61     ans = ans * inv[n] % mod;
62 }
63 inline void pre() {
64     int lim = n + 1;
65     *fac = 1;
66     for(int i=1;i<=lim;i++) fac[i] = fac[i-1] * i % mod;
67     inv[lim] = fastpow(fac[lim],mod-2);
68     for(int i=lim;i;i--) inv[i-1] = inv[i] * i % mod;
69 }
70 
71 int main() {
72     scanf("%d%d",&n,&m);
73     pre() , getans();
74     printf("%lld
",ans);
75     return 0;
76 }
View Code


T2:


n方暴力很好写吧......
考虑二维平面,一条路径相当于让两边花式取min,然后不会写了。
写了一个大力random_shuffle也没有骗到subtask2的分......
正解是分治,考虑我们把这个东西划分成多个三角形,然后枚举中间的一条边,分别计算经过这条边两个点的询问的代价并递归计算两边询问的代价。
因为显然两个点分别在这条边两边的询问的最有路径至少过这条边两个端点中的一个......
然而这种分治可能把一个求解区间变成上下两个不连通的联通快......所以在更新时需要特判一下-1,在递归边界也要特判......
话说第一次写这个我还写傻了,写了8kb代码死活调不出来......后来重构了才成功AC。
25分暴力代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 #define debug cout
 8 using namespace std;
 9 const int maxn=1e5+1e2;
10 
11 struct Node {
12     int y,id;
13 };
14 struct QNode {
15     int siz,id;
16     friend bool operator < (const QNode &a,const QNode &b) {
17         return a.siz < b.siz;
18     }
19 };
20 vector<Node> qs[maxn];
21 priority_queue<QNode> pq;
22 queue<int> q;
23 vector<int> vec[maxn];
24 int siz[maxn],dis[maxn],ans[maxn];
25 int n,m;
26 
27 inline void bfs(int st) {
28     memset(dis,-1,sizeof(int)*n) , dis[st] = 0;
29     q.push(st);
30     while( q.size() ) {
31         const int pos = q.front(); q.pop();
32         for(unsigned j=0;j<vec[pos].size();j++)
33             if( !~dis[vec[pos][j]] )
34                 dis[vec[pos][j]] = dis[pos] + 1 ,
35                 q.push(vec[pos][j]);
36     }
37 }
38 inline void getans(const QNode &d) {
39     if( siz[d.id] != d.siz ) return;
40     const int id = d.id; bfs(id);
41     for(unsigned i=0;i<qs[id].size();i++)
42         if( !ans[qs[id][i].id] ) {
43             ans[qs[id][i].id] = dis[qs[id][i].y] ,
44             pq.push((QNode){--siz[qs[id][i].y],qs[id][i].y});
45         }
46 }
47 inline void getans() {
48     while( pq.size() ) {
49         getans(pq.top()) , pq.pop();
50     }
51 }
52 inline void shufall() {
53     srand(19260817);
54     for(int i=0;i<n;i++) random_shuffle(vec[i].begin(),vec[i].end());
55 }
56 
57 int main() {
58     scanf("%d",&n);
59     for(int i=0;i<n;i++) {
60         vec[i].push_back(i!=n-1?i+1:0) ,
61         vec[i].push_back(i?i-1:n-1);
62     }
63     for(int i=1,a,b;i<=n-3;i++) {
64         scanf("%d%d",&a,&b) ,
65         vec[a].push_back(b) ,
66         vec[b].push_back(a) ;
67     }
68     shufall() , scanf("%d",&m);
69     for(int i=1,a,b;i<=m;i++) {
70         scanf("%d%d",&a,&b);
71         qs[a].push_back((Node){b,i}) ,
72         qs[b].push_back((Node){a,i}) ;
73     }
74     for(int i=0;i<n;i++) pq.push((QNode){siz[i]=qs[i].size(),i});
75     getans();
76     for(int i=1;i<=m;i++) printf("%d
",ans[i]);
77     return 0;
78 }
View Code

正解代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<queue>
  7 #include<cstdlib>
  8 #define debug cout
  9 using namespace std;
 10 const int maxn=1e5+1e2;
 11 const int inf=0x3f3f3f3f;
 12 
 13 struct Query {
 14     int a,b,id;
 15 };
 16 int s[maxn],t[maxn<<2],nxt[maxn<<2];
 17 int disx[maxn],disy[maxn],id[maxn],pt[maxn],iid,cnt;
 18 vector<Query> qs;
 19 vector<int> ps;
 20 int ans[maxn];
 21 
 22 inline void addedge(int from,int to) {
 23     static int cnt = 0;
 24     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 25     swap(from,to);
 26     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 27 }
 28 
 29 inline void bfs(int st,int* dis) {
 30     queue<int> q; dis[st] = 0 , q.push(st);
 31     while( q.size() ) {
 32         const int pos = q.front(); q.pop();
 33         for(int at=s[pos];at;at=nxt[at])
 34             if( !~dis[t[at]] && id[t[at]] == id[pos] )
 35                 dis[t[at]] = dis[pos] + 1 , q.push(t[at]);
 36     }
 37 }
 38 
 39 inline void solve(const vector<int> &ps,const vector<Query> &qs) {
 40     if( !qs.size() ) return;
 41     if( ps.size() <= 3 ) {
 42         ++iid;
 43         for(unsigned i=0;i<ps.size();i++) disx[ps[i]] = disy[ps[i]] = -1 , id[ps[i]] = iid;
 44         int x = ps[0] , y = ps[1];
 45         bfs(x,disx) , bfs(y,disy);
 46         for(unsigned i=0;i<qs.size();i++) {
 47             if( ~disx[qs[i].a] && ~disx[qs[i].b] ) ans[qs[i].id] = min( ans[qs[i].id] , disx[qs[i].a] + disx[qs[i].b] );
 48             if( ~disy[qs[i].a] && ~disy[qs[i].b] ) ans[qs[i].id] = min( ans[qs[i].id] , disy[qs[i].a] + disy[qs[i].b] );
 49         }
 50         return;
 51     }
 52     ++iid , cnt = 0;
 53     for(unsigned i=0;i<ps.size();i++) {
 54         disx[ps[i]] = disy[ps[i]] = -1 ,
 55         id[ps[i]] = iid , pt[ps[i]] = ++cnt;
 56     }
 57     int miv = inf , x = 0 , y = 0;
 58     for(unsigned i=0;i<ps.size();i++) {
 59         const int pos = ps[i];
 60         for(int at=s[pos];at;at=nxt[at])
 61             if( id[t[at]] == iid ) {
 62                 const int lam = max( abs(pt[t[at]]-pt[pos]) , (signed) ps.size() - abs(pt[t[at]]-pt[pos]) );
 63                 if( lam < miv ) miv = lam , x = pos , y = t[at];
 64             }
 65     }
 66     if( pt[x] > pt[y] ) swap(x,y);
 67     bfs(x,disx) , bfs(y,disy);
 68     vector<int> pl,pr;
 69     vector<Query> ql,qr;
 70     for(unsigned i=0;i<qs.size();i++) {
 71         if( ~disx[qs[i].a] && ~disx[qs[i].b] ) ans[qs[i].id] = min( ans[qs[i].id] , disx[qs[i].a] + disx[qs[i].b] );
 72         if( ~disy[qs[i].a] && ~disy[qs[i].b] ) ans[qs[i].id] = min( ans[qs[i].id] , disy[qs[i].a] + disy[qs[i].b] );
 73         if( qs[i].a == x || qs[i].b == x || qs[i].a == y || qs[i].b == y ) continue;
 74         if( pt[x] < pt[qs[i].a] && pt[qs[i].a] < pt[y] && pt[x] < pt[qs[i].b] && pt[qs[i].b] < pt[y] ) ql.push_back(qs[i]);
 75         if( ! ( pt[x] <= pt[qs[i].a] && pt[qs[i].a] <= pt[y] ) && ! ( pt[x] <= pt[qs[i].b] && pt[qs[i].b] <= pt[y] ) ) qr.push_back(qs[i]);
 76     }
 77     for(unsigned i=0;i<ps.size();i++) {
 78         if( ps[i] == x || ps[i] == y ) continue;
 79         if( pt[x] < pt[ps[i]] && pt[ps[i]] < pt[y] ) pl.push_back(ps[i]);
 80         if( ! ( pt[x] <= pt[ps[i]] && pt[ps[i]] <= pt[y] ) ) pr.push_back(ps[i]);
 81     }
 82     solve(pl,ql) , solve(pr,qr);
 83 }
 84 
 85 int main() {
 86     static int n,m;
 87     scanf("%d",&n);
 88     for(int i=0;i<n;i++) {
 89         addedge(i,(i+1)%n) ,
 90         ps.push_back(i);
 91     }
 92     for(int i=1,a,b;i<=n-3;i++)
 93         scanf("%d%d",&a,&b) , addedge(a,b);
 94     scanf("%d",&m) , memset(ans,0x3f,sizeof(ans));
 95     for(int i=1,a,b;i<=m;i++) {
 96         scanf("%d%d",&a,&b) , qs.push_back((Query){a,b,i});
 97     }
 98     solve(ps,qs);
 99     for(int i=1;i<=m;i++) printf("%d
",ans[i]);
100     return 0;
101 }
View Code

写傻了的代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<set>
  6 #include<map>
  7 #include<queue>
  8 #include<vector>
  9 #include<cassert>
 10 #define debug cout
 11 using namespace std;
 12 const int maxn=1e5+1e2;
 13 const int inf=0x3f3f3f3f;
 14 
 15 struct Query {
 16     int a,b,id;
 17 };
 18 vector<pair<int,int> > es;
 19 vector<Query> qs;
 20 vector<int> tp,ps;
 21 int ans[maxn],n,m;
 22 
 23 namespace Graph {
 24     int s[maxn],t[maxn<<2],nxt[maxn<<2],disx[maxn],disy[maxn];
 25     queue<int> q;
 26     
 27     inline void coredge(int from,int to) {
 28         static int cnt = 0;
 29         t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 30     }
 31     inline void doubledge(int a,int b) {
 32         coredge(a,b) , coredge(b,a);
 33     }
 34     inline void bfs(int st,int* dis) {
 35         q.push(st) , dis[st] = 0;
 36         while( q.size() ) {
 37             const int pos = q.front(); q.pop();
 38             for(int at=s[pos];at;at=nxt[at]) if( !~dis[t[at]] )
 39                 dis[t[at]] = dis[pos] + 1 , q.push(t[at]);
 40         }
 41     }
 42     inline void solve(const vector<int> &ps,const vector<Query> &qs,int x,int y) {
 43         for(unsigned i=0;i<ps.size();i++) disx[ps[i]] = disy[ps[i]] = -1;
 44         bfs(x,disx) , bfs(y,disy);
 45         for(unsigned i=0;i<qs.size();i++) {
 46             ans[qs[i].id] = min( ans[qs[i].id] , min( disx[qs[i].a] + disy[qs[i].b] , disx[qs[i].b] + disy[qs[i].a] ) + 1 );
 47             ans[qs[i].id] = min( ans[qs[i].id] , min( disx[qs[i].a] + disx[qs[i].b] , disy[qs[i].b] + disy[qs[i].a] ) );
 48         }
 49     }
 50 }
 51 
 52 namespace TreeDivideAndConqure {
 53     int s[maxn],t[maxn<<1],nxt[maxn<<1],x[maxn<<1],y[maxn<<1];
 54     int id[maxn],siz[maxn],iid,miv,mip,mipfa;
 55     inline void coredge(int from,int to,int xx,int yy) {
 56         static int cnt = 0;
 57         //debug<<"from = "<<from<<"to = "<<to<<endl;
 58         t[++cnt] = to , x[cnt] = xx , y[cnt] = yy ,
 59         nxt[cnt] = s[from] , s[from] = cnt;
 60     }
 61     inline void addedge(int a,int b,int xx,int yy) {
 62         int x = min( x , xx ) , y = max( y , yy );
 63         coredge(a,b,x,y) , coredge(b,a,x,y);
 64     }
 65 }
 66 
 67 namespace GetTriangle {
 68     struct Triangle {
 69         int x,y,z;
 70         Triangle() { x = y = z = -1; }
 71         Triangle(int xx,int yy,int zz) {
 72             static int tp[3];
 73             tp[0] = xx , tp[1] = yy , tp[2] = zz;
 74             sort(tp,tp+3);
 75             //debug<<"x = "<<xx<<"y = "<<yy<<"z = "<<zz<<endl;
 76             x = tp[0] , y = tp[1] , z = tp[2];
 77         }
 78         friend bool operator < (const Triangle &a,const Triangle &b) {
 79             if( a.x != b.x ) return a.x < b.x;
 80             if( a.y != b.y ) return a.y < b.y;
 81             return a.z < b.z;
 82         }
 83     }rec[maxn];
 84     
 85     priority_queue<pair<unsigned,int> > pq;
 86     map<Triangle,int> mp;
 87     set<int> es[maxn];
 88     int deg[maxn],tcnt;
 89     
 90     inline void getdualpoint(const int &x,int &y,int &z) {
 91         y = z = -1;
 92         for(set<int>::iterator it=es[x].begin();it!=es[x].end();it++) {
 93             if( !~y ) y = *it;
 94             else z = *it;
 95         }
 96     }
 97     inline Triangle getbypoint(const int &x) {
 98         assert(es[x].size()==2);
 99         int y,z;
100         getdualpoint(x,y,z);
101         return Triangle(x,y,z);
102     }
103     inline void cutpoint(const pair<unsigned,int> &pir) {
104         const int x = pir.second;
105         if( -pir.first != es[x].size() ) return;
106         if( es[x].size() < 2 ) return;
107         //debug<<"in cutpoint x = "<<pir.second<<endl;
108         int y,z;
109         getdualpoint(x,y,z);
110         //debug<<"y = "<<y<<"z = "<<z<<endl;
111         Triangle now = Triangle(x,y,z) , nxt;
112         if( mp.find(now) == mp.end() ) mp[now] = ++tcnt , rec[tcnt] = now;
113         es[x].erase(y) , es[y].erase(x) ,
114         es[x].erase(z) , es[z].erase(x) ;
115         if( es[y].size() == 2 ) nxt = getbypoint(y);
116         else if( es[z].size() == 2 ) nxt = getbypoint(z);
117         if( ~nxt.x ) {
118             if( mp.find(nxt) == mp.end() ) mp[nxt] = ++tcnt , rec[tcnt] = nxt;
119             TreeDivideAndConqure::addedge(mp[now],mp[nxt],y,z);
120         }
121         pq.push(make_pair(-es[y].size(),y)) , pq.push(make_pair(-es[z].size(),z));
122     }
123     inline void work() {
124         for(int i=0;i<n;i++) pq.push(make_pair(-es[i].size(),i));
125         while( pq.size() ) cutpoint(pq.top()) , pq.pop();
126     }
127 }
128 
129 namespace TreeDivideAndConqure {
130     inline void dfs(int pos,int fa,const int &fs,int &rx,int &ry) {
131         //debug<<"pos = "<<pos<<endl;
132         siz[pos] = 1;
133         for(int at=s[pos];at;at=nxt[at])
134             if( id[t[at]] == iid && t[at] != fa ) {
135                 dfs(t[at],pos,fs,rx,ry) , siz[pos] += siz[t[at]];
136                 //debug<<"max = "<<max(siz[t[at]],fs-siz[t[at]])<<endl;
137                 if( max(siz[t[at]],fs-siz[t[at]]) < miv ) {
138                     
139                     rx = x[at] , ry = y[at] ,
140                     miv = max(siz[t[at]],fs-siz[t[at]]) ,
141                     mip = t[at] , mipfa = pos;
142                 }
143             }
144     }
145     inline void spit(int pos,int fa,vector<int> &ret) {
146         ret.push_back(pos);
147         for(int at=s[pos];at;at=nxt[at])
148             if( id[t[at]] == iid && t[at] != fa )
149                 spit(t[at],pos,ret);
150     }
151     #define judge1(l,r,x) ( l < x && x < r )
152     #define judge2(l,r,x) ( ! ( l <= x && x <= r ) )
153     inline void solve(const vector<int> &tps,const vector<int> &ps,const vector<pair<int,int> > es,const vector<Query> qs) {
154         if( tps.size() < 1 || ps.size() <= 1 || !es.size() || !qs.size() ) return;
155         //debug<<"in solve"<<endl;
156         ++iid;
157         for(unsigned i=0;i<tps.size();i++) id[tps[i]] = iid;
158         //debug<<"tps = "; for(unsigned i=0;i<tps.size();i++) debug<<tps[i]<<" "; debug<<endl;
159         //debug<<"ps = "; for(unsigned i=0;i<ps.size();i++) debug<<ps[i]<<" "; debug<<endl;
160         int x,y;
161         miv = inf , dfs(tps[0],-1,tps.size(),x,y);
162         //debug<<"x = "<<x<<"y = "<<y<<endl;
163         Graph::solve(ps,qs,x,y);
164         vector<int> tpl,tpr;
165         spit(mip,mipfa,tpl) , spit(mipfa,mip,tpr);
166         vector<int> pl,pr;
167         vector<pair<int,int> > el,er;
168         vector<Query> ql,qr;
169         for(unsigned i=0;i<ps.size();i++) {
170             if( judge1(x,y,ps[i]) ) pl.push_back(ps[i]);
171             if( judge2(x,y,ps[i]) ) pr.push_back(ps[i]);
172         }
173         for(unsigned i=0;i<es.size();i++) {
174             if( judge1(x,y,es[i].first) && judge1(x,y,es[i].second) ) el.push_back(es[i]);
175             if( judge2(x,y,es[i].first) && judge2(x,y,es[i].second) ) er.push_back(es[i]);
176         }
177         for(unsigned i=0;i<qs.size();i++) {
178             if( judge1(x,y,qs[i].a) && judge1(x,y,qs[i].b) ) ql.push_back(qs[i]);
179             if( judge2(x,y,qs[i].a) && judge2(x,y,qs[i].b) ) qr.push_back(qs[i]);
180         }
181         if( tpl.size() && tpr.size() && GetTriangle::rec[tpl[0]].x > GetTriangle::rec[tpr[0]].x ) swap(tpl,tpr);
182         /*debug<<"tpl = "; for(unsigned i=0;i<tpl.size();i++) debug<<tpl[i]<<" "; debug<<endl;
183         debug<<"tpr = "; for(unsigned i=0;i<tpr.size();i++) debug<<tpr[i]<<" "; debug<<endl;
184         debug<<"pl = "; for(unsigned i=0;i<pl.size();i++) debug<<pl[i]<<" "; debug<<endl;
185         debug<<"pr = "; for(unsigned i=0;i<pr.size();i++) debug<<pr[i]<<" "; debug<<endl;*/
186         solve(tpl,pl,el,ql) , solve(tpr,pr,er,qr);
187     }
188 }
189 
190 inline void addedge(int x,int y) {
191     if( x > y ) swap(x,y);
192     es.push_back(make_pair(x,y));
193     GetTriangle::es[x].insert(y) , GetTriangle::es[y].insert(x);
194     Graph::doubledge(x,y);
195 }
196 int main() {
197     static int m;
198     scanf("%d",&n);
199     for(int i=0;i<n;i++)
200         addedge(i,(i+1)%n);
201     for(int i=1,a,b;i<=n-3;i++)
202         scanf("%d%d",&a,&b) , addedge(a,b);
203     scanf("%d",&m);
204     for(int i=1,a,b;i<=m;i++) {
205         scanf("%d%d",&a,&b);
206         qs.push_back((Query){a,b,i});
207     }
208     memset(ans,0x3f,sizeof(ans));
209     GetTriangle::work();
210     //for(unsigned i=1;i<=GetTriangle::tcnt;i++) debug<<GetTriangle::rec[i].x<<" "<<GetTriangle::rec[i].y<<" "<<GetTriangle::rec[i].z<<endl;
211     //exit(0);
212     for(int i=0;i<n;i++) ps.push_back(i);
213     for(int i=1;i<=GetTriangle::tcnt;i++) tp.push_back(i);
214     TreeDivideAndConqure::solve(tp,ps,es,qs);
215     for(int i=1;i<=m;i++)
216         printf("%d
",ans[i]);
217     return 0;
218 }
View Code


T3:


显然答案不能在区间不是单调不增的时候为len,否则为1。
n方暴力依然好写。
只有加的情况也很容易。
于是我考场上写了自调整分块trick过了40分......
但是在处理取min的时候存在问题,不能AC。
正解是线段树,然而我并不会jry线段树。
于是考虑乱搞,维护区间min,区间max,后面有一个更大的值的最小的umin,然后合并时讨论一下就好了。
两个标记的话让加法优于取min,因为我们能在min上进行加法修改。应用的时候先加法即可。
40分分块代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #define debug cout
  7 typedef long long int lli;
  8 using namespace std;
  9 const int maxn=1e5+1e2,maxb=319;
 10 const lli inf=0x3f3f3f3f3f3f3f3fll;
 11 
 12 int bel[maxn],st[maxb],ed[maxb];
 13 lli in[maxn],lazy_add[maxb],lazy_min[maxb],mxv[maxb],miv[maxb];
 14 bool flag[maxb];
 15 int n;
 16 
 17 inline void block_add(int pos,int l,int r,lli t) {
 18     l = max( l , st[pos] ) , r = min( r , ed[pos] ) , flag[pos] = 0;
 19     for(int i=l;i<=r;i++) {
 20         in[i] += t;
 21         if( i != l ) flag[pos] |= ( in[i-1] < in[i] );
 22     }
 23 }
 24 inline void block_min(int pos,int l,int r,lli t) {
 25     l = max( l , st[pos] ) , r = min( r , ed[pos] ) , flag[pos] = 0;
 26     for(int i=l;i<=r;i++) {
 27         in[i] = min( in[i] , t );
 28         if( i != l ) flag[pos] |= ( in[i-1] < in[i] );
 29     }
 30 }
 31 inline void rebuild_blk(int pos) {
 32     miv[pos] = inf , mxv[pos] = 0 , flag[pos] = 0;
 33     for(int i=st[pos];i<=ed[pos];i++) {
 34         miv[pos] = min( miv[pos] , in[i] ) ,
 35         mxv[pos] = max( mxv[pos] , in[i] ) ;
 36         if( i != st[pos] ) flag[pos] |= ( in[i-1] < in[i] ) ;
 37     }
 38 }
 39 inline void push_lazy(int pos) {
 40     int fail = 1;
 41     if( lazy_add[pos] ) {
 42         block_add(pos,st[pos],ed[pos],lazy_add[pos]);
 43         lazy_add[pos] = 0 , fail = 0;
 44     }
 45     if( lazy_min[pos] < inf ) {
 46         block_min(pos,st[pos],ed[pos],lazy_min[pos]);
 47         lazy_min[pos] = inf , fail = 0;
 48     }
 49     if( !fail ) rebuild_blk(pos);
 50 }
 51 inline void fully_add(int pos,lli x) {
 52     lazy_add[pos] += x , lazy_min[pos] += x ,
 53     miv[pos] += x , mxv[pos] += x;
 54 }
 55 inline void fully_min(int pos,lli x) {
 56     lazy_min[pos] = min( miv[pos] , x ) ,
 57     miv[pos] = min( miv[pos] , x ) ,
 58     mxv[pos] = min( mxv[pos] , x ) ;
 59 }
 60 inline void partly_add(int pos,int l,int r,lli x) {
 61     push_lazy(pos) ,
 62     block_add(pos,l,r,x) ,
 63     rebuild_blk(pos) ;
 64 }
 65 inline void partly_min(int pos,int l,int r,lli x) {
 66     push_lazy(pos) ,
 67     block_min(pos,l,r,x) ,
 68     rebuild_blk(pos) ;
 69 }
 70 inline void update_add(int l,int r,lli x) {
 71     if( bel[l] == bel[r] ) return partly_add(bel[l],l,r,x);
 72     for(int i=bel[l]+1;i<bel[r];i++) fully_add(i,x);
 73     partly_add(bel[l],l,r,x) , partly_add(bel[r],l,r,x);
 74 }
 75 inline void update_min(int l,int r,lli x) {
 76     if( bel[l] == bel[r] ) return partly_min(bel[l],l,r,x);
 77     for(int i=bel[l]+1;i<bel[r];i++) fully_min(i,x);
 78     partly_min(bel[l],l,r,x) , partly_min(bel[r],l,r,x);
 79 }
 80 inline bool query_part(int pos,int l,int r,lli& miv,lli& mxv) {
 81     push_lazy(pos);
 82     l = max( l , st[pos] ) , r = min( r , ed[pos] );
 83     miv = inf , mxv = 0;
 84     bool ret = 0;
 85     for(int i=l;i<=r;i++) {
 86         miv = min( miv , in[i] ) , mxv = max( mxv , in[i] ) ;
 87         if( i != l ) ret |= ( in[i-1] < in[i] );
 88     }
 89     return ret;
 90 }
 91 inline bool query(int l,int r) {
 92     lli smiv,tp,x;
 93     if( bel[l] == bel[r] ) return query_part(bel[l],l,r,smiv,tp);
 94     bool ret = query_part(bel[l],l,r,smiv,tp);
 95     for(int i=bel[l]+1;i<bel[r];i++) {
 96         ret |= flag[i] , ret |= ( smiv < mxv[i] ) , smiv = min( smiv , miv[i] );
 97         if( ret ) return ret;
 98     }
 99     ret |= query_part(bel[r],l,r,x,tp) , ret |= ( smiv < tp );
100     return ret;
101 }
102 
103 inline void build(bool flag) {
104     const int blksiz = flag ? n : sqrt(n);
105     int cnt = 0;
106     for(int l=1,r;l<=n;l=r+1) {
107         r = min( l + blksiz - 1 , n ) , ++cnt;
108         st[cnt] = l , ed[cnt] = r , lazy_min[cnt] = inf;
109         for(int i=l;i<=r;i++) bel[i] = cnt;
110         rebuild_blk(cnt);
111     }
112 }
113 
114 int main() {
115     static int m;
116     scanf("%d%d",&n,&m);
117     for(int i=1;i<=n;i++) scanf("%lld",in+i);
118     build(n<=1000);
119     for(int i=1,t,l,r,x;i<=m;i++) {
120         scanf("%d%d%d",&t,&l,&r);
121         if( t == 3 ) printf("%d
",query(l,r)?r-l+1:1);
122         else {
123             scanf("%d",&x);
124             if( t == 1 ) update_add(l,r,x);
125             else if( t == 2 ) update_min(l,r,x);
126         }
127     }
128     return 0;
129 }
View Code

正解代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define debug cout
  6 typedef long long int lli;
  7 using namespace std;
  8 const int maxn=1e5+1e2;
  9 const lli inf=0x3f3f3f3f3f3f3f3fll,lim=inf>>4;
 10 
 11 struct Node {
 12     lli miv,mxv,umiv,umxv;
 13     friend Node operator + (const Node &a,const Node &b) {
 14          Node ret = (Node){min(a.miv,b.miv),max(a.mxv,b.mxv),inf,-inf};
 15          if( a.miv < b.mxv ) ret.umiv = a.miv , ret.umxv = b.mxv;
 16          if( a.umiv < ret.umiv ) ret.umiv = a.umiv , ret.mxv = max( a.umxv , b.mxv );
 17          if( b.umiv < ret.umiv ) ret.umiv = b.umiv , ret.umxv = b.umxv;
 18          return ret;
 19     }
 20     inline void fill(const int &x) {
 21         miv = mxv = x , umiv = inf , umxv = -inf;
 22     }
 23     inline void apply_add(const lli &x) {
 24         miv +=x , mxv +=x , umiv += x , umxv += x;
 25     }
 26     inline void apply_min(const lli &x) {
 27         miv = min( miv , x ) , mxv= min( mxv , x );
 28         if( umiv < x ) umxv = max( umxv , x );
 29         else umiv = inf , umxv = -inf;
 30     }
 31 }ns[maxn<<3];
 32 
 33 int in[maxn];
 34 int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3],cnt;
 35 lli lazy_add[maxn<<3],lazy_min[maxn<<3];
 36 
 37 inline void build(int pos,int ll,int rr) {
 38     l[pos] = ll , r[pos] = rr;
 39     if( ll == rr ) return ns[pos].fill(in[ll]);
 40     const int mid = ( ll + rr ) >> 1;
 41     build(lson[pos]=++cnt,ll,mid) , build(rson[pos]=++cnt,mid+1,rr);
 42     ns[pos] = ns[lson[pos]] + ns[rson[pos]];
 43 }
 44 inline void apply_add(int pos,const lli &x) {
 45     lazy_add[pos] += x , lazy_min[pos] += x ,
 46     ns[pos].apply_add(x);
 47 }
 48 inline void apply_min(int pos,const lli &x) {
 49     lazy_min[pos] = min( lazy_min[pos] , x ) ,
 50     ns[pos].apply_min(x);
 51 }
 52 inline void push(int pos) {
 53     if( lazy_add[pos] ) {
 54         apply_add(lson[pos],lazy_add[pos]) , apply_add(rson[pos],lazy_add[pos]) ,
 55         lazy_add[pos] = 0;
 56     }
 57     if( lazy_min[pos] < lim ) {
 58         apply_min(lson[pos],lazy_min[pos]) , apply_min(rson[pos],lazy_min[pos]) ,
 59         lazy_min[pos] = inf;
 60     }
 61 }
 62 inline void update_add(int pos,int ll,int rr,const lli &x) {
 63     if( rr < l[pos] || r[pos] < ll ) return;
 64     if( ll <= l[pos] && r[pos] <= rr ) return apply_add(pos,x);
 65     push(pos);
 66     update_add(lson[pos],ll,rr,x) , update_add(rson[pos],ll,rr,x) ,
 67     ns[pos] = ns[lson[pos]] + ns[rson[pos]] ;
 68 }
 69 inline void update_min(int pos,int ll,int rr,const lli &x) {
 70     if( rr < l[pos] || r[pos] < ll ) return;
 71     if( ll <= l[pos] && r[pos] <= rr ) return apply_min(pos,x);
 72     push(pos);
 73     update_min(lson[pos],ll,rr,x) , update_min(rson[pos],ll,rr,x) ,
 74     ns[pos] = ns[lson[pos]] + ns[rson[pos]];
 75 }
 76 inline Node query(int pos,int ll,int rr) {
 77     if( ll <= l[pos] && r[pos] <= rr ) return ns[pos];
 78     push(pos);
 79     const int mid = ( l[pos] + r[pos] ) >> 1;
 80     if( rr <= mid ) return query(lson[pos],ll,rr);
 81     if( ll > mid ) return query(rson[pos],ll,rr);
 82     const Node ql = query(lson[pos],ll,rr) , qr = query(rson[pos],ll,rr);
 83     return ql + qr;
 84 }
 85 
 86 int main() {
 87     static int n,m;
 88     scanf("%d%d",&n,&m) , memset(lazy_min,0x3f,sizeof(lazy_min));
 89     for(int i=1;i<=n;i++) scanf("%d",in+i);
 90     build(cnt=1,1,n);
 91     for(int i=1,o,l,r,x;i<=m;i++) {
 92         scanf("%d%d%d",&o,&l,&r);
 93         if( o == 3 ) {
 94             Node ans = query(1,l,r);
 95             printf("%d
",ans.umiv<lim?r-l+1:1);
 96         } else {
 97             scanf("%d",&x);
 98             if( o == 1 ) update_add(1,l,r,x);
 99             else if( o ==2 ) update_min(1,l,r,x);
100         }
101     }
102     return 0;
103 }
View Code
原文地址:https://www.cnblogs.com/Cmd2001/p/8647595.html