@LittleRewriter
2017-10-08T03:21:04.000000Z
字数 4946
阅读 775
题解 爆零
暴力
简单的容斥
容斥硬搞
暴力枚举一下,求一个lcm然后算一算
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> pr;const double pi=acos(-1);#define rep(i,a,n) for(int i=a;i<=n;i++)#define per(i,n,a) for(int i=n;i>=a;i--)#define Rep(i,u) for(int i=head[u];i;i=Next[i])#define clr(a) memset(a,0,sizeof a)#define pb push_back#define mp make_pair#define putk() putchar(' ')ld eps=1e-9;ll pp=1000000007;ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}ll gcd(ll a,ll b){return (!b)?a:gcd(b,a%b);}ll read(){ll ans=0;char last=' ',ch=getchar();while(ch<'0' || ch>'9')last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans;return ans;}void put(ll a){if(a<0)putchar('-'),a=-a;int top=0,q[20];while(a)q[++top]=a%10,a/=10;top=max(top,1);while(top--)putchar('0'+q[top+1]);}//headll ans=0;int n,m,a[25];ll Gcd(ll a,ll b){if(!b)return a;return gcd(b,a%b);}void dfs(int dep,ll t,int flag){if(t>n)return;if(dep==m+1){ans+=n/t*flag;return;}dfs(dep+1,t,flag);dfs(dep+1,t/Gcd(t,a[dep])*a[dep],-flag);}int main(){n=read();m=read();rep(i,1,m)a[i]=read();dfs(1,1,1);cout<<ans<<endl;return 0;}
取出,排序,中位数即可,然后再排个序
固定左端点
新出现一个区间就用下一个元素插排O(n)更新一下
最后求k大
求第k大可以二分答案。
以中位数>=k的区间个数有多少来二分
那么大于等于k设置为1,否则设置为-1.如果这些和加起来大于等于0,就说明这个区间的中位数是>=k的。
暴力统计每个区间的总和即可
考虑上述做法,相当于统计S[R]>S[L-1]的对数。
其实相当于求顺序对。用树状数组维护即可。
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> pr;const double pi=acos(-1);#define rep(i,a,n) for(int i=a;i<=n;i++)#define per(i,n,a) for(int i=n;i>=a;i--)#define Rep(i,u) for(int i=head[u];i;i=Next[i])#define clr(a) memset(a,0,sizeof a)#define pb push_back#define mp make_pair#define fi first#define sc secondld eps=1e-9;ll pp=1000000007;ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}ll read(){ll ans=0;char last=' ',ch=getchar();while(ch<'0' || ch>'9')last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans;return ans;}//head#define N 110000int a[N],b[N],c[N],d[N],e[N],n,m;ll k;int lowbit(int x){return x&(-x);}int bin(int k){int l=1,r=m;while(l<r){int mid=(l+r)/2;if(k<=d[mid])r=mid;else l=mid+1;}return l;}void add(int x){for(;x<=m;x+=lowbit(x))e[x]++;}int find(int x){int ans=0;for(;x;x-=lowbit(x))ans+=e[x];return ans;}ll check(int k){c[0]=0;rep(i,1,n)c[i]=c[i-1]+(a[i]>=k);rep(i,0,n)c[i]=c[i]*2-i,d[i+1]=c[i];sort(d+1,d+n+2);d[0]=1;rep(i,2,n+1)if(d[i]!=d[d[0]])d[++d[0]]=d[i];m=d[0];ll ans=0;rep(i,0,n)c[i]=bin(c[i]);rep(i,0,m)e[i]=0;rep(i,0,n)if(i&1)add(c[i]);else ans+=find(c[i]-1);rep(i,0,m)e[i]=0;rep(i,0,n)if((i&1)==0)add(c[i]);else ans+=find(c[i]-1);return ans;}int main(){n=read();k=read();rep(i,1,n)a[i]=read(),b[i]=a[i];sort(b+1,b+n+1);b[0]=1;rep(i,2,n)if(b[i]!=b[b[0]])b[++b[0]]=b[i];int l=1,r=b[0];while(l<r){int mid=(l+r)/2+1;ll tt=check(b[mid]);if(tt==k){cout<<b[mid]<<endl;return 0;}if(check(b[mid])>k)l=mid;else r=mid-1;}cout<<b[l]<<endl;return 0;}
枚举每个区间,排序,求前缀和,爆算一下
枚举区间,右端点递增,插入排序,然后前缀和维护
一个数字在所有区间被统计的次数总和就是小于它的区间个数总和
对于j来说,比k小的数的下标有
那么这些东西的贡献,在(n-j+1)个区间中,贡献总和就是
也就是求出所有比k小的数的位置的下标总和
对于t在k右边,反过来求即可。
枚举比它小的数可以暴力一下,总复杂度
我们的操作是查询比它小的下标总和,将这个数存入数组中。
可以用树状数组来维护,也可以归并排序。
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> pr;const double pi=acos(-1);#define rep(i,a,n) for(int i=a;i<=n;i++)#define per(i,n,a) for(int i=n;i>=a;i--)#define Rep(i,u) for(int i=head[u];i;i=Next[i])#define clr(a) memset(a,0,sizeof a)#define pb push_back#define mp make_pair#define fi first#define sc secondld eps=1e-9;ll pp=1000000007;ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}ll read(){ll ans=0;char last=' ',ch=getchar();while(ch<'0' || ch>'9')last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans;return ans;}//head#define N 1100000pr a[N];int c1[N],c2[N],n;ll A,B,C;int lowbit(int x){return x&(-x);}void add(int *c,int x,int w){c[0]+=w;if(c[0]>=pp)c[0]-=pp;for(;x<=n;x+=lowbit(x)){c[x]=c[x]+w;if(c[x]>=pp)c[x]-=pp;}}int find(int *c,int x){int ans=0;for(;x;x-=lowbit(x)){ans+=c[x];if(ans>=pp)ans-=pp;}return ans;}int main(){cin>>n>>a[1].fi>>A>>B>>C;a[1].sc=1;rep(i,2,n){a[i].sc=i;a[i].fi=(a[i-1].fi*A+B)%C;}sort(a+1,a+n+1);ll ans=0;rep(i,1,n){int t1=find(c1,a[i].sc);int t2=c2[0]-find(c2,a[i].sc-1);t2=(t2+pp)%pp;int t3=(1ll*t1*(n-a[i].sc+1)+1ll*t2*a[i].sc)%pp;t3=(t3+1ll*a[i].sc*(n-a[i].sc+1))%pp;ans=(ans+1ll*t3*a[i].fi)%pp;add(c1,a[i].sc,a[i].sc);add(c2,a[i].sc,n-a[i].sc+1);}cout<<ans<<endl;return 0;}