bzoj 4597||洛谷P4340 [Shoi2016]随机序列

https://www.lydsy.com/JudgeOnline/problem.php?id=4597

https://www.luogu.org/problemnew/show/P4340

妄图直接暴力维护一堆东西,以直接维护题目要求的值(具体见代码...)

最后花了2个小时维护完了,A掉了,然而好像常数比别人大一倍?

上网搜题解,发现大部分东西都可以抵消掉??回想维护过程中,好像有一堆抵消掉的东西?

看来即使可以暴力维护,也还是要多观察题目性质...

  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<ll,ll> pii;
 13 const ll md=1e9+7;
 14 ll n,q;
 15 ll a[100100];
 16 ll pw3[100100];
 17 const ll N=400100;
 18 #define lc (num<<1)
 19 #define rc (num<<1|1)
 20 ll d1[N],d2[N],d3[N],d4[N],d5[N];
 21 //d1:区间乘积
 22 //d2:区间和
 23 //d3:除了全部是乘号外,所有选择方案靠左边全是乘号一段的积的和
 24 //d4:除了全部是乘号外,...靠右边...(带符号)
 25 //d5:答案
 26 //维护过程中发现d4必定为0...
 27 /*
 28    举例:1,2,3
 29    1+2+3,1+2-3,1+2*3,
 30    1-2+3,1-2-3,1-2*3,
 31    1*2+3,1*2-3,1*2*3
 32    d3应当维护1*6+1*2*2=10
 33    d4应当维护3*3-3*3+2*3-2*3=0
 34 */
 35 void upd(ll l,ll r,ll num)
 36 {
 37     d1[num]=d1[lc]*d1[rc]%md;
 38     d2[num]=(d2[lc]+d2[rc])%md;
 39     ll mid=l+((r-l)>>1);
 40     d3[num]=(d3[lc]*pw3[r-mid]%md+d1[lc]*2*pw3[r-(mid+1)]%md
 41         +d1[lc]*d3[rc]%md)%md;
 42     d4[num]=(d4[rc]*pw3[mid-l+1]%md//+d1[rc]*2*pw3[mid-l]%md
 43         +d1[rc]*d4[lc]%md)%md;
 44     ll d4l=(d4[lc]+d1[lc])%md,d3r=(d3[rc]+d1[rc])%md;
 45     /*
 46     d5[num]=(2*(r-mid)*d5[lc]%md+(r-mid)*((d5[lc]-d4l+md)%md)%md
 47         +(mid-l+1)*((d5[rc]-d3r+md)%md)%md
 48         +d4l*d3r%md)%md;
 49     */
 50     ll m=pw3[mid-l],n=pw3[r-(mid+1)];
 51     /*
 52     d5[num]=(2*(r-mid)*d5[lc]%md+2*(mid-l+1)*d5[rc]%md
 53         +pw3[mid-l]*(md-2)%md*d3r%md
 54         +(r-mid)*((d5[lc]-d4l+md)%md)%md
 55         +(mid-l+1)*((d5[rc]-d3r+md)%md)%md
 56         +d4l*d3r%md)%md;
 57     */
 58     d5[num]=(2*n*d5[lc]%md+2*m*d5[rc]%md
 59         +m*(md-2)%md*d3r%md
 60         +n*((d5[lc]-d4l+md)%md)%md
 61         +m*((d5[rc]-d3r+md)%md)%md
 62         +d4l*d3r%md)%md;
 63 
 64     /*
 65     d5[num]=(2*(r-mid)*d5[lc]%md+2*(mid-l+1)*d5[rc]%md
 66         +pw3[mid-l]*(md-2)%md*d3r%md
 67         +(r-mid)*((d5[lc]-d4l+md)%md)%md
 68         +
 69     printf("1t%lld %lld %lld %lld %lld %lld %lld\n",l,r,d1[num],d2[num],
 70         d3[num],d4[num],d5[num]);
 71     printf("2t%lld %lld %lld\n",(r-mid)*d5[lc]%md+(mid-l+1)*d5[rc]%md,
 72         (r-mid)*d5[lc]%md+(mid-l+1)*d5[rc]%md+pw3[mid-l]*(md-2)%md*d3r%md,
 73         (r-mid)*((d5[lc]-d4l+md)%md)%md
 74         +(mid-l+1)*((d5[rc]-d3r+md)%md)%md
 75         +d4l*d3r%md);
 76     */
 77 }
 78 void pre(ll l,ll num,ll x)
 79 {
 80     d1[num]=x;
 81     d2[num]=x;
 82     d3[num]=d4[num]=0;
 83     d5[num]=x;
 84 }
 85 void build(ll l,ll r,ll num)
 86 {
 87     if(l==r)    {pre(l,num,a[l]);return;}
 88     ll mid=l+((r-l)>>1);
 89     build(l,mid,lc);build(mid+1,r,rc);
 90     upd(l,r,num);
 91 }
 92 void setx(ll L,ll x,ll l,ll r,ll num)
 93 {
 94     if(l==r)    {pre(l,num,x);return;}
 95     ll mid=l+((r-l)>>1);
 96     if(L<=mid)    setx(L,x,l,mid,lc);
 97     else    setx(L,x,mid+1,r,rc);
 98     upd(l,r,num);
 99 }
100 int main()
101 {
102     ll i,x,y;
103     pw3[0]=1;
104     for(i=1;i<=100000;i++)
105         pw3[i]=pw3[i-1]*3%md;
106     scanf("%lld%lld",&n,&q);
107     for(i=1;i<=n;i++)    scanf("%lld",&a[i]);
108     build(1,n,1);
109     //printf("%lld %lld %lld %lld %lld",d1[1],d2[1],d3[1],d4[1],d5[1]);
110     while(q--)
111     {
112         scanf("%lld%lld",&x,&y);
113         setx(x,y,1,n,1);
114         printf("%lld\n",d5[1]);
115     }
116     return 0;
117 }
View Code

 

posted @ 2018-10-19 20:25  hehe_54321  阅读(141)  评论(0编辑  收藏  举报
AmazingCounters.com