炸弹
来源:互联网 发布:一组数据如何找规律 编辑:程序博客网 时间:2024/04/28 04:29
题意:在一些坐标上有一些炸弹。。有两个操作
1、移动炸弹,,把一个炸弹从一个坐标移到另一个坐标。
2、询问一段坐标中所有炸弹坐标中大坐标减去小坐标。
思路:离散化,把所有可能出现的坐标点找出来排好序后,去重。
把所有坐标都映射到他所对应的在数组的索引号,用map实现。
用res记录段的坐标差和,sum记录所有坐标之和,cnt记录有多少个地雷。
更新res=res1+res2+cnt1*sum2-cnt2*sum1;
sum=sum1+sum2;
cnt=cnt1+cnt2;
查找时的结果res要依靠sum和cnt所以返回类型为tree,并且更新只在返回的结构体中更新。
#include<iostream>#include<cstdio>#include<map>#include<algorithm>using namespace std;#define N 100010int n,q;struct tree{int left,right;int mid;long long res,sum,cnt;}t[N*12];map<long long,int> m;struct car {int flag;long long from,to;}ask[N];long long hi[2*N];int nhi;long long go[N];void build(int cur,int l,int r){t[cur].mid=(l+r)>>1;t[cur].left=l;t[cur].right=r;t[cur].res=t[cur].sum=t[cur].cnt=0;if (l!=r){build(cur<<1,l,t[cur].mid);build(cur<<1|1,t[cur].mid+1,r);}}void add(int cur,int l){if (t[cur].left==t[cur].right){t[cur].sum=hi[l];t[cur].cnt=1;t[cur].res=0;return;}int L=cur<<1,R=cur<<1|1;int m=t[cur].mid;if (l<=m)add(L,l);else add(R,l);t[cur].sum=t[L].sum+t[R].sum;t[cur].cnt=t[L].cnt+t[R].cnt;t[cur].res=t[L].res+t[R].res+t[L].cnt*t[R].sum-t[R].cnt*t[L].sum;}void remove(int cur,int l){if (t[cur].left==t[cur].right){t[cur].sum=0;t[cur].cnt=0;t[cur].res=0;return;}int L=cur<<1,R=cur<<1|1;int m=t[cur].mid;if (l<=m)remove(L,l);else remove(R,l);t[cur].sum=t[L].sum+t[R].sum;t[cur].cnt=t[L].cnt+t[R].cnt;t[cur].res=t[L].res+t[R].res+t[L].cnt*t[R].sum-t[R].cnt*t[L].sum;}tree query(int cur,int l,int r){if (l<=t[cur].left && r>=t[cur].right){return t[cur];}int m=t[cur].mid;int L=cur<<1,R=cur<<1|1;if (r<=m)return query(L,l,r);else if (l>m)return query(R,l,r);tree LL=query(L,l,r);tree RR=query(R,l,r);tree ans;ans.res=LL.res+RR.res+RR.sum*LL.cnt-LL.sum*RR.cnt;ans.sum=LL.sum+RR.sum;ans.cnt=LL.cnt+RR.cnt;return ans;}int main(){freopen("in.txt","r",stdin);int i,j,k;int nc;cin>>nc;while (nc--){scanf("%d",&n);for (i=0;i<n;i++){scanf("%d",&k);go[i]=k;hi[i]=k;}nhi=n;scanf("%d",&q);for (int ii=0;ii<q;ii++){scanf("%d%d%d",&k,&i,&j);if (k==1){go[i-1]+=j;hi[nhi++]=go[i-1];}else{hi[nhi++]=i;hi[nhi++]=j;}ask[ii].flag=k;ask[ii].from=i;ask[ii].to=j;}for (i=0;i<n;i++)go[i]=hi[i];sort(hi,hi+nhi);j=1;for (i=1;i<nhi;i++)if (hi[i]!=hi[i-1])hi[j++]=hi[i];nhi=j;for (i=0;i<nhi;i++)m[hi[i]]=i;build(1,0,nhi-1);for (i=0;i<n;i++)add(1,m[go[i]]);for (i=0;i<q;i++){if (ask[i].flag==1){remove(1,m[go[ask[i].from-1]]);//cout<<go[ask[i].from]<<' ';go[ask[i].from-1]+=ask[i].to;//cout<<go[ask[i].from]<<endl;add(1,m[go[ask[i].from-1]]);}else{//cout<<ask[i].from<<' '<<ask[i].to<<' '<<m[ask[i].from]<<' '<<m[ask[i].to]<<endl;printf("%lld\n",query(1,m[ask[i].from],m[ask[i].to]).res);}}}return 0;}
贪玩的xie
Time Limit: 5000 ms Memory Limit: 65535 kB Solved:25 Tried: 222
Description
Xie是一个很无聊的人,他最喜欢的事就是随手拿一些可怕的东西来玩。
现在,xie在x轴上放了n个地雷。第一个地雷的坐标是x1,第二个的坐标是x2,..,第n个的坐标是xn。
现在xie有m个关于这些地雷的询问,每个询问分为以下两类:
1.把第pj个地雷从所在的位置xpj移动到xpj+dj。数据保证,每次移动之后,每个地雷的坐标都不同。
2.为了评估地雷爆炸的威力,计算线段[lj,rj]上的每对地雷的距离之和。也就是说,要计算
Input
第一行一个整数T,表示数据组数。
每组数据第一行一个整数n(1<=n<=10^5),地雷的数量。第二行包含n个不同的整数x1,x2,…,xn,表示地雷的坐标。
第三行有一个整数m,代表询问的数量(1<=m<=10^5).接下来m行描述这些询问。第j行的第一个整数tj(1<=tj<=2),表示询问的类型。如果tj=1,那么接下来会有两个整数pj和 dj(1<=pj<=n,|dj|<=1000)。如果tj=2,那么会有两个整数lj,rj(-10^9 < lj <= rj <= 10^9)
保证任意时刻,所有的地雷都在不同的坐标上。
Output
对于每个第2类型的询问,输出一行答案。输出答案请按询问出现的顺序来输出。
Sample Input
1
8
36 50 28 -75 40 -60 -95 -48
20
2 -61 29
1 5 -53
1 1 429
1 5 130
2 -101 -71
2 -69 53
1 1 404
1 5 518
2 -101 53
2 50 872
1 1 -207
2 -99 -40
1 7 -389
1 6 -171
1 2 464
1 7 -707
1 1 -730
1 1 560
2 635 644
1 7 -677
Sample Output
17620
406
1046
1638
156
0
- 炸弹
- 炸弹
- 炸弹
- 炸弹
- 炸弹
- txt炸弹
- 网页炸弹
- 糖果炸弹
- google炸弹
- fork 炸弹
- 批处理炸弹
- fork 炸弹
- fork炸弹
- fork炸弹
- 蓝屏炸弹
- fork 炸弹
- 炸弹人
- 炸弹人
- linux异步信号handle浅析
- Edit Box 详解2
- 程序员的生活
- 设计模式概述
- 编译原理 实验1 词法分析程序的构造
- 炸弹
- com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error:
- 前端工具汇总(不定期更新)
- win7下vs2008解决cd-key输入框显示问题
- sdut.acm区间覆盖问题
- ACM各个阶段的一些要求
- 关于扩展欧几里德算法的理解
- 剑指offer面试题41和为s的两个数字VS和为s的连续正数序列
- oracle实现left join的两种写法