fzu 1656 How many different numbers(线段树)
来源:互联网 发布:check it 编辑:程序博客网 时间:2024/06/05 17:55
题意:询问不同区间不同值的个数
//思路1 700+ms#include<iostream>#include<string>#include<algorithm>using namespace std;#define CL(a,b) memset(a,b,sizeof(a))const int M(100010);const int N(1020);int f[N],r[M];struct data{int x,sub;}a[M];struct dat{int l,r;int sub;}ans[N];int vis[M];bool cmp(data x,data y){return x.x<y.x;}bool cm(dat x,dat y ){return x.l<y.l||(x.l==y.l&&x.r<y.r);}int main(){int m,i,n,j,q;while(scanf("%d",&m)!=EOF){for(i=1;i<=m;i++){scanf("%d",&a[i].x);a[i].sub=i;}sort(a+1,a+m+1,cmp);r[a[1].sub]=0;for(i=2,j=0;i<=m;i++)//离散化{if(a[i-1].x==a[i].x)r[a[i].sub]=j;else{j++;r[a[i].sub]=j;}}scanf("%d",&q);for(i=0;i<q;i++){scanf("%d%d",&ans[i].l,&ans[i].r);ans[i].sub=i;}sort(ans,ans+q,cm);CL(f,0); CL(vis,0);//vis记录出现个数for(i=0;i<q;i++){if(i==0){CL(vis,0);for(j=ans[i].l;j<=ans[i].r;j++){if(!vis[r[j]])f[ans[i].sub]++;vis[r[j]]++;}continue;}if(ans[i].r<ans[i-1].r){if((ans[i].l-ans[i-1].l+ans[i-1].r-ans[i].r)>(ans[i].r-ans[i].l)){CL(vis,0);for(j=ans[i].l;j<=ans[i].r;j++){if(!vis[r[j]])f[ans[i].sub]++;vis[r[j]]++;}}else{f[ans[i].sub]=f[ans[i-1].sub];for(j=ans[i-1].l;j<ans[i].l;j++){vis[r[j]]--;if(vis[r[j]]==0)f[ans[i].sub]--;}for(j=ans[i].r+1;j<=ans[i-1].r;j++){vis[r[j]]--;if(vis[r[j]]==0)f[ans[i].sub]--;}}}else {if((ans[i].l-ans[i-1].l)>(ans[i-1].r-ans[i].l)){CL(vis,0);for(j=ans[i].l;j<=ans[i].r;j++){if(!vis[r[j]])f[ans[i].sub]++;vis[r[j]]++;}}else{f[ans[i].sub]=f[ans[i-1].sub];for(j=ans[i-1].l;j<ans[i].l;j++){vis[r[j]]--;if(vis[r[j]]==0)f[ans[i].sub]--;}for(j=ans[i-1].r+1;j<=ans[i].r;j++){if(!vis[r[j]])f[ans[i].sub]++;vis[r[j]]++;}}}}for(i=0;i<q;i++)printf("%d\n",f[i]);}}//参考:http://blog.csdn.net/sqplfh/article/details/6840996
具体思路:先把N个保存下来,进行离散,然后用就可以用flag记录某个数前面出现的位置,再把询问保存下来,按右端点排序。
对N个数依次处理,删除该数前面出现的,在当前位置插入该数。当处理到第i个位置的数,且询问的右端点也为i是,统计个数。
// 300+ms 线段树优化#include<iostream>#include<string>#include<algorithm>using namespace std;#define CL(a,b) memset(a,b,sizeof(a))#define MID(a,b) (a+b)>>1const int M(100010);const int N(1020);int tree[M<<2],r[M],f[N];struct data{int x,sub;}a[M];struct dat{int l,r;int sub;}ans[N];int vis[M];bool cmp(data x,data y){return x.x<y.x;}bool cm(dat x,dat y ){return x.r<y.r;}inline void pushup(int t){tree[t]=tree[t<<1]+tree[t<<1|1];}void insert(int t,int x,int val,int l,int r){if(l==r){tree[t]=val;return;}int mid=MID(l,r);if(x<=mid)insert(t<<1,x,val,l,mid);if(x>mid)insert(t<<1|1,x,val,mid+1,r);pushup(t);}int query(int t,int ql,int qr,int l,int r){if(ql<=l&&qr>=r)return tree[t];int mid=MID(l,r);if(qr<=mid)return query(t<<1,ql,qr,l,mid);else if(ql>mid)return query(t<<1|1,ql,qr,mid+1,r);elsereturn query(t<<1,ql,qr,l,mid)+query(t<<1|1,ql,qr,mid+1,r);}int main(){int m,i,n,j,q;while(scanf("%d",&m)!=EOF){for(i=1;i<=m;i++){scanf("%d",&a[i].x);a[i].sub=i;}sort(a+1,a+m+1,cmp);r[a[1].sub]=0;for(i=2,j=0;i<=m;i++){if(a[i-1].x==a[i].x)r[a[i].sub]=j;else{j++;r[a[i].sub]=j;}}scanf("%d",&q);for(i=0;i<q;i++){scanf("%d%d",&ans[i].l,&ans[i].r);ans[i].sub=i;}sort(ans,ans+q,cm);CL(vis,-1); CL(tree,0);for(i=1,j=0;i<=m&&j<q;i++){if(vis[r[i]]!=-1){insert(1,vis[r[i]],0,1,m);}insert(1,i,1,1,m);vis[r[i]]=i;while(i==ans[j].r){f[ans[j].sub]=query(1,ans[j].l,ans[j].r,1,m);j++;//printf("%d\n",tree[1]);}}for(i=0;i<q;i++)printf("%d\n",f[i]);}}
- fzu 1656 How many different numbers(线段树)
- FZU 1656 How many different numbers
- 1656 How many different numbers
- 1656 How many different numbers
- How many different numbers
- FOJ 1656 How many different numbers
- FZUOJ1656-How many different numbers解题技巧
- How many prime numbers
- How many prime numbers
- How many prime numbers
- How many prime numbers
- How many prime numbers
- How many prime numbers
- hdu How many prime numbers
- hdu2138 How many prime numbers
- How many prime numbers 2138
- HDU2138 How many prime numbers
- HDU How many prime numbers
- C++ - 多重继承和虚拟继承对象模型、效率分析
- mysql 中 unix_timestamp和from_unixtime 时间戳函数
- POJ 1338
- Android的EditText控件点击虚拟键盘上的回车怎么跳到下一个EditText继续输入呢?
- 【ACM Steps】 Fibonacci
- fzu 1656 How many different numbers(线段树)
- .Net反射用到的基本方法
- ABAP 使用Smartforms发送HTML邮件
- 浅谈C#中的枚举
- Android本机调试服务器地址
- 【ACM Steps】 The 3n + 1 problem
- vs2008下编译bochs-2.4.6
- SAP 物料订单创建、下达、报工、收货与投料(ABAP代码)
- 去除Visual Studio 红色波浪线