ZROI2018提高day3t2

传送门

分析

我们设A[i]表示点i有几个矿,B[i]表示这之中有几个矿是第一次出现,所以点i的贡献即为

   (2^B[i]-1)*(2^(A[i]-B[i]))

注意减一的原因是第一次出现的矿应至少有一个。然后我们用set维护一下就可以了。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const long long mod = 998244353;
struct node {
      long long x,y;
};
node d[500100];
set<long long>s;
inline bool cmp(const node a,const node b){
      if(a.x==b.x)return a.y>b.y;
      return a.x<b.x;
}
long long pw2[500100];
int main(){
      long long n,m,sum=0,ans=0,i,j,k,cnt=0;
      scanf("%lld%lld",&n,&m);
      pw2[0]=1;
      for(i=1;i<=n;i++)pw2[i]=pw2[i-1]*2%mod;
      for(i=1;i<=n;i++){
          long long x,y;
          scanf("%lld%lld",&x,&y);
          d[++cnt].x=x,d[cnt].y=i;
          d[++cnt].x=y,d[cnt].y=-i;
      }
      for(i=1;i<=m;i++){
          long long x;
          scanf("%lld",&x);
          d[++cnt].x=x;
      }
      sort(d+1,d+cnt+1,cmp);
      for(i=1;i<=cnt;i++){
          if(!d[i].y){
          ans=(ans+(pw2[s.size()]-1)*pw2[sum-s.size()]%mod)%mod;
          s.clear();
        }
        if(d[i].y>0)s.insert(d[i].y),sum++;
        if(d[i].y<0)s.erase(-d[i].y),sum--;
      }
      printf("%lld\n",ans);
      return 0;
}
posted @ 2018-09-15 09:18  水题收割者  阅读(116)  评论(0编辑  收藏  举报