2020牛客暑期多校训练营（第九场）C Groundhog and Gaming Time 题解

(a+b+c+d+e)^2=a*(a+b+c+d+e)+b*(a+b+c+d+e)+c*(a+b+c+d+e)+d*(a+b+c+d+e)+e*(a+b+c+d+e)

(a+b+c)^2+(c+d+e)^2=…… c*(a+b+c)+c*(c+d+e) ……

=…… c*((a+b+c)+(c+d+e)) ……

  1 #include<iostream>
2 #include<cstdlib>
3 #include<cstdio>
4 #include<cstring>
5 #include<cmath>
6 #include<algorithm>
7 #include<map>
8 #define N 500005
9 using namespace std;
10 int n;
11 struct ro{
12     int l,r;
13 }A[N];
14 const int p=998244353;
15 int inv;
16 int B[N],C[N];
17 bool cmpl(int x,int y)
18 {
19     return A[x].l<A[y].l;
20 }
21 bool cmpr(int x,int y)
22 {
23     return A[x].r<A[y].r;
24 }
25 map<int,int>ma;
26 int zz,D[2*N];
27 struct no{
28     int left,right,mid;
29     long long sum,tmp;
30 }node[N*8];
31 void build(int left,int right,int x)
32 {
33     node[x].left=left,node[x].right=right;
34     node[x].tmp=1;                        //tmp表示这个区间被覆盖了log2(tmp)次
35     node[x].sum=D[right+1]-D[left];        //sum表示这个区间的贡献和
36     if(left==right)
37     {
38         return;
39     }
40     int mid=(left+right)>>1;
41     node[x].mid=mid;
42     build(left,mid,x<<1);
43     build(mid+1,right,x<<1|1);
44 }
45 long long ksm(long long x,long long z)
46 {
47     long long ans=1;
48     while(z)
49     {
50         if(z&1)
51         {
52             ans=ans*x%p;
53         }
54         x=x*x%p;
55         z>>=1;
56     }
57     return ans;
58 }
59 void change(int left,int right,int x,int da)
60 {
61     if(node[x].left==left&&node[x].right==right)
62     {
63         node[x].sum=node[x].sum*da%p;
64         node[x].tmp=node[x].tmp*da%p;
65         return ;
66     }
67     int mid=node[x].mid;
68     if(left>mid) change(left,right,x<<1|1,da);
69     else if(right<=mid) change(left,right,x<<1,da);
70     else change(left,mid,x<<1,da),change(mid+1,right,x<<1|1,da);
71     node[x].sum=(node[x<<1].sum+node[x<<1|1].sum)%p*node[x].tmp%p;
72 }
73 int main()
74 {
75     inv=ksm(2,p-2);
76     scanf("%d",&n);
77     for(int i=1;i<=n;i++)
78     {
79         scanf("%d%d",&A[i].l,&A[i].r);
80         A[i].r++;                    //方便计算让右端点+1
81         B[i]=C[i]=i;
82         if(!ma[A[i].l])
83         {
84             zz++;
85             D[zz]=A[i].l;
86             ma[A[i].l]=1;
87         }
88         if(!ma[A[i].r])
89         {
90             zz++;
91             D[zz]=A[i].r;
92             ma[A[i].r]=1;
93         }
94     }
95     if(!ma[0])                        //在外面套上一个边界，方便计算
96     {
97         zz++;
98         D[zz]=0;
99         ma[0]=zz;
100     }
101     if(!ma[1e9+1])
102     {
103         zz++;
104         D[zz]=1e9+1;
105         ma[1e9+1]=zz;
106     }
107     sort(B+1,B+n+1,cmpl);            //将区间按照左端点排序
108     sort(C+1,C+n+1,cmpr);            //将区间按照右端点排序
109     sort(D+1,D+zz+1);
110     for(int i=1;i<=zz;i++)
111     {
112         ma[D[i]]=i;
113     }
114     int li=1,ri=1;
115     build(1,zz-1,1);
116     long long ans=0;
117     for(int i=1;i<zz;i++)
118     {
119         for(;A[B[li]].l<=D[i]&&li<=n;li++)    //计算新的对 [ D[i],D[i+1]) 有影响的大区间 的贡献
120         {
121             change(ma[A[B[li]].l],ma[A[B[li]].r]-1,1,2);
122         }
123
124         for(;A[C[ri]].r<=D[i]&&ri<=n;ri++) //消去新的不对[ D[i],D[i+1]) 有影响的大区间 的贡献
125         {
126             change(ma[A[C[ri]].l],ma[A[C[ri]].r]-1,1,inv);
127         }
128         ans=(ans+1ll*node[1].sum*(D[i+1]-D[i])%p)%p;
129     }
130     ans=(ans-1ll*(1000000001)*(1000000001)%p+p)%p;     // 减去多算的那部分贡献
131     ans=ans*ksm(inv,n)%p;                           //除以2^n
132     printf("%lld\n",ans%p);
133     return 0;
134 }
View Code

posted @ 2020-09-01 21:54  Hzoi_joker  阅读(254)  评论(0编辑  收藏  举报