Lucky Array Codeforces - 121E && Bear and Bad Powers of 42 Codeforces - 679E
http://codeforces.com/contest/121/problem/E
话说这题貌似暴力可A啊。。。
正解是想出来了,结果重构代码,调了不知道多久才A
错误记录:
1.线段树搞混num(节点编号)和l(区间端点)
2.之前的dfs没有分离,写的非常混乱,迫不得已重构代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<int,int> pii; 13 #define N 100000 14 int data[80]={4,7,44,47,74,77,444,447,474,477,744,747,774,777, 15 4444,4447,4474,4477,4744,4747,4774,4777,7444,7447,7474,7477, 16 7744,7747,7774,7777}; 17 bool ok[10010]; 18 int sd=30; 19 int n,m; 20 int d[N+100]; 21 vector<pii> qq; 22 //d[i]表示满足data[j]>(i位置的实际值)的最小j 23 //线段树中查询出的位置的值表示data[d[i]]-(i位置的实际值) 24 namespace S 25 { 26 #define mid (l+((r-l)>>1)) 27 #define lc (num<<1) 28 #define rc (num<<1|1) 29 int minn[4*N],sum[4*N],delv[4*N]; 30 void pd(int num) 31 { 32 minn[lc]-=delv[num];minn[rc]-=delv[num]; 33 delv[lc]+=delv[num];delv[rc]+=delv[num]; 34 delv[num]=0; 35 } 36 void delx(int L,int R,int x,int l,int r,int num) 37 { 38 if(L<=l&&r<=R) 39 { 40 minn[num]-=x;delv[num]+=x; 41 return; 42 } 43 pd(num); 44 if(L<=mid) delx(L,R,x,l,mid,lc); 45 if(mid<R) delx(L,R,x,mid+1,r,rc); 46 minn[num]=min(minn[lc],minn[rc]); 47 } 48 void setx(int L,int x,int l,int r,int num) 49 { 50 if(l==r) {minn[num]=x;return;} 51 pd(num); 52 if(L<=mid) setx(L,x,l,mid,lc); 53 else setx(L,x,mid+1,r,rc); 54 minn[num]=min(minn[lc],minn[rc]); 55 } 56 void setsum(int L,int x,int l,int r,int num) 57 { 58 if(l==r) {sum[num]=x;return;} 59 if(L<=mid) setsum(L,x,l,mid,lc); 60 else setsum(L,x,mid+1,r,rc); 61 sum[num]=sum[lc]+sum[rc]; 62 } 63 void update(int l,int r,int num) 64 { 65 if(minn[num]>0) return; 66 if(l==r) {qq.pb(mp(l,data[d[l]]-minn[num]));return;}//minn[l]->minn[num] 67 pd(num); 68 update(l,mid,lc);update(mid+1,r,rc); 69 minn[num]=min(minn[lc],minn[rc]); 70 } 71 int gsum(int L,int R,int l,int r,int num) 72 { 73 if(L<=l&&r<=R) return sum[num]; 74 int ans=0; 75 if(L<=mid) ans+=gsum(L,R,l,mid,lc); 76 if(mid<R) ans+=gsum(L,R,mid+1,r,rc); 77 return ans; 78 } 79 void work() 80 { 81 for(auto pp:qq) 82 { 83 int &l=pp.fi,&d=pp.se; 84 int p=upper_bound(data,data+sd,d)-data; 85 setx(l,data[p]-d,1,n,1); 86 setsum(l,ok[d],1,n,1); 87 ::d[l]=p; 88 } 89 qq.clear(); 90 } 91 } 92 char tmp[10]; 93 int main() 94 { 95 int i,t,L,R,x; 96 for(i=0;i<sd;i++) ok[data[i]]=1; 97 for(i=0;i<sd;i++) data[i+sd]=data[i]+1; 98 sd*=2;sort(data,data+sd); 99 data[sd++]=12000; 100 scanf("%d%d",&n,&m); 101 for(i=1;i<=n;i++) scanf("%d",&t),qq.pb(mp(i,t)); 102 S::work(); 103 while(m--) 104 { 105 scanf("%s",tmp); 106 if(tmp[0]=='c') 107 { 108 scanf("%d%d",&L,&R);S::update(1,n,1);S::work(); 109 printf("%d\n",S::gsum(L,R,1,n,1)); 110 } 111 else 112 { 113 scanf("%d%d%d",&L,&R,&x); 114 S::delx(L,R,x,1,n,1); 115 } 116 } 117 return 0; 118 }
https://codeforces.com/problemset/problem/679/E
跟上面那道类似,可以发现涉及到42的幂很少(显然出题人不是想让我们写高精)
因此开一棵线段树维护每个位置到下一个“关键点”(是否是42的幂的属性变化的点)的距离即可
对于区间修改,就用set维护一下相同的区间,一段相同的放在一起处理
大概是这样吧,可能还有一些细节。。