CF85D Sum of Medians
题意翻译
一个集合,初始为空。现有三个操作:
1.add:向集合里加入数x,保证加入前集合中没有数x;
2.del:从集合中删除数x,保证删除前集合中有x;
3.sum:询问将集合里的数从小到大排序后,求下标i模5余3的数的和。
现有n次操作,对于每个查询操作,输出答案
题解Here!
一开始感觉好不可做啊。。。
然后发现,线段树好像可以搞一搞。
线段树每个节点维护5个值,即区间中所有\text{下标}\mod5后结果相同的位置的值的和。
即:在区间[l,r]上维护:
\sum_{i=l}^rv_i[i\mod 5==0],\sum_{i=l}^rv_i[i\mod 5==1],\sum_{i=l}^rv_i[i\mod 5==2],\sum_{i=l}^rv_i[i\mod 5==3],\sum_{i=l}^rv_i[i\mod 5==4]
再维护区间中有多少个值num。
合并的时候左子树不动,右子树中所有\text{下标}\mod5==x的位置应该是((i-num)\%5+5)\%5。
至于线段树怎么动态加点。。。
其实离线一下就可以把线段树搞成静态,然后离散化一下就好。
记得开long\ long。
还与就是在CF上是不能用\%lld来读入、输出long\ long,所以还是老老实实用cin,cout。。。
附代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | #include<iostream> #include<algorithm> #include<cstdio> #define LSON rt<<1 #define RSON rt<<1|1 #define DATA(x,k) a[x].data[k] #define NUM(x) a[x].num #define LSIDE(x) a[x].l #define RSIDE(x) a[x].r #define MAXN 100010 using namespace std; int n,m=0; int lsh[MAXN]; struct Question{ int f,x; }que[MAXN]; struct Segment_Tree{ long long data[5]; int num,l,r; }a[MAXN<<2]; inline int read(){ int date=0,w=1; char c=0; while (c< '0' ||c> '9' ){ if (c== '-' )w=-1;c= getchar ();} while (c>= '0' &&c<= '9' ){date=date*10+c- '0' ;c= getchar ();} return date*w; } inline void pushup( int rt){ NUM(rt)=NUM(LSON)+NUM(RSON); for ( int i=0;i<5;i++)DATA(rt,i)=DATA(LSON,i)+DATA(RSON,((i-NUM(LSON))%5+5)%5); } void buildtree( int l, int r, int rt){ LSIDE(rt)=l;RSIDE(rt)=r;NUM(rt)=0; if (l>=r) return ; int mid=l+r>>1; buildtree(l,mid,LSON); buildtree(mid+1,r,RSON); } void update( int k, int c, long long v, int rt){ if (LSIDE(rt)==RSIDE(rt)){ DATA(rt,1)+=v; NUM(rt)+=c; return ; } int mid=LSIDE(rt)+RSIDE(rt)>>1; if (k<=mid)update(k,c,v,LSON); else update(k,c,v,RSON); pushup(rt); } void work(){ for ( int i=1,x;i<=n;i++){ if (que[i].f==1){ x=lower_bound(lsh+1,lsh+m+1,que[i].x)-lsh; update(x,1,que[i].x,1); } else if (que[i].f==-1){ x=lower_bound(lsh+1,lsh+m+1,que[i].x)-lsh; update(x,-1,-que[i].x,1); } else cout<<DATA(1,3)<<endl; } } void init(){ char ch[2]; n=read(); for ( int i=1,x;i<=n;i++){ scanf ( "%s" ,ch); if (ch[0]== 'a' ){ x=read(); lsh[++m]=que[i].x=x; que[i].f=1; } else if (ch[0]== 'd' ){ x=read(); que[i].x=x; que[i].f=-1; } else que[i].f=0; } sort(lsh+1,lsh+m+1); m=unique(lsh+1,lsh+m+1)-lsh-1; buildtree(1,m,1); } int main(){ init(); work(); return 0; } |
其实还有一种更暴力的方法:
vector大法好!
各种STL乱搞就好。
附代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include<iostream> #include<algorithm> #include<cstdio> #include<vector> using namespace std; int n; vector< int > a; inline int read(){ int date=0,w=1; char c=0; while (c< '0' ||c> '9' ){ if (c== '-' )w=-1;c= getchar ();} while (c>= '0' &&c<= '9' ){date=date*10+c- '0' ;c= getchar ();} return date*w; } void work(){ char ch[2]; n=read(); for ( int i=1,x;i<=n;i++){ scanf ( "%s" ,ch); if (ch[0]== 'a' ){ x=read(); a.insert(lower_bound(a.begin(),a.end(),x),x); } else if (ch[0]== 'd' ){ x=read(); a.erase(lower_bound(a.begin(),a.end(),x)); } else { long long ans=0; for ( int i=2;i<a.size();i+=5)ans+=a[i]; cout<<ans<<endl; } } } int main(){ work(); return 0; } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· MQ 如何保证数据一致性?