北京集训: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\n",ans); 75 return 0; 76 }
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\n",ans[i]); 77 return 0; 78 }
正解代码:
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\n",ans[i]); 100 return 0; 101 }
写傻了的代码:
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\n",ans[i]); 217 return 0; 218 }
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\n",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 }
正解代码:
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\n",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 }