NBUT 1457 Sona (莫队算法)
2016-08-05 15:36
197 查看
题意:
给出一个数列,求区间内相同数字次数的三次方和
分析:
离散化数字之后直接莫队
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 100005
struct node
{
int l,r;
int id;
} q[maxn];
vector<int>v;
long long ans[maxn];
int vis[maxn];
int a[maxn];
int block[maxn];
long long sum;
bool cmp(node A,node B)
{
if(block[A.l]==block[B.l]) return A.r<B.r;
return block[A.l]<block[B.l];
}
long long cal(long long x)
{
return 3*x*x+3*x+1;
}
void update(int add,int note)
{
if(add==-1) sum-=cal(vis[note]-1),vis[note]--;
else sum+=cal(vis[note]),vis[note]++;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(vis,0,sizeof vis);
v.clear();
int bk=sqrt(n*1.0);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
v.push_back(a[i]);
block[i]=(i/bk)+1;
}
block[n+1]=block
+1;
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1; i<=n; i++)
{
a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin();
a[i]++;
}
int m;
scanf("%d",&m);
for(int i=0; i<m; i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q,q+m,cmp);
int l=0,r=1;
sum=0;
for(int i=0; i<m; i++)
{
for(; r<=q[i].r; r++) update(1,a[r]);
for(; r-1>q[i].r; r--) update(-1,a[r-1]);
for(; l+1<q[i].l; l++) update(-1,a[l+1]);
for(; l>=q[i].l; l--) update(1,a[l]);
ans[q[i].id]=sum;
}
for(int i=0; i<m; i++)
{
printf("%I64d\n",ans[i]);
}
}
return 0;
}
给出一个数列,求区间内相同数字次数的三次方和
分析:
离散化数字之后直接莫队
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 100005
struct node
{
int l,r;
int id;
} q[maxn];
vector<int>v;
long long ans[maxn];
int vis[maxn];
int a[maxn];
int block[maxn];
long long sum;
bool cmp(node A,node B)
{
if(block[A.l]==block[B.l]) return A.r<B.r;
return block[A.l]<block[B.l];
}
long long cal(long long x)
{
return 3*x*x+3*x+1;
}
void update(int add,int note)
{
if(add==-1) sum-=cal(vis[note]-1),vis[note]--;
else sum+=cal(vis[note]),vis[note]++;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(vis,0,sizeof vis);
v.clear();
int bk=sqrt(n*1.0);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
v.push_back(a[i]);
block[i]=(i/bk)+1;
}
block[n+1]=block
+1;
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1; i<=n; i++)
{
a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin();
a[i]++;
}
int m;
scanf("%d",&m);
for(int i=0; i<m; i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q,q+m,cmp);
int l=0,r=1;
sum=0;
for(int i=0; i<m; i++)
{
for(; r<=q[i].r; r++) update(1,a[r]);
for(; r-1>q[i].r; r--) update(-1,a[r-1]);
for(; l+1<q[i].l; l++) update(-1,a[l+1]);
for(; l>=q[i].l; l--) update(1,a[l]);
ans[q[i].id]=sum;
}
for(int i=0; i<m; i++)
{
printf("%I64d\n",ans[i]);
}
}
return 0;
}
相关文章推荐
- CentOS Linux 下安装Samba
- C++-->类
- Activity的生命周期
- mailto: HTML e-mail 链接
- Oracle数据类型隐式转换小析
- java反射拼接方法名动态执行方法实例
- 安卓app接入微信支付
- 【网络】网络基础知识总结(包括TCP/IP协议、ARP、UDP等)
- [SpringBoot]构建SpringBoot项目 By Eclipse
- HDU 2222 AC自动机 入门题
- Spacebuilder在Mono上运行修改备忘
- HDU 4731 找规律,打表
- discuz!X3分类信息调用-主题列表页调用分类信息字段
- mysql的外键
- C++内存池实现
- 从设备像素比到移动适配
- OrmLite的封装
- Android总结篇系列:Android广播机制
- POJ3308
- 超过一定行数的label强制在末尾加上一个...展开且可以点击成全文