暑假集训8.7数据结构专题-很妙的线段树( 觉醒力量(hidpower))

题目:oj1710

因为存在修改和查询的操作,所以学长说可以很“轻易”的想到线段树....,装作我轻易的想到了,最后是要输出答案mod17及mod46189的结果,(关键点1)然后我们发现46189=11*13*17*19;于是我们想到但处理出答案mod每个质因数的答案,再利用中国剩余定理求出答案。(关键点2)考虑对枚举进入某各区间运算的数为1-p[i],因为p[i]很小所以可以处理。然后修改操作也变成log的。非常可写。

关于中国剩余定理:x=(∑ai*ti*mi)modM。ti是逆元。

上代码:

#include<bits/stdc++.h>
#define il inline
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
string s[17]={"Fight","Flying","Poison","Ground","Rock","Bug","Ghost","Steel","Fire","Water","Grass","Electric","Psychic","Ice","Dragon","Dark","Fairy"};
const int N=1e5+5;int n,m,p[5]={0,11,13,17,19},k[5],P=46189;
struct node{char ch;int a;}q[N];struct data{int b[5][20];}t[N<<2];
int read(){int x,f=1;char ch;_(!)ch==‘-‘?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;}
int ksm(int x,int y,int p){int b=x,ans=1;while(y){if(y&1)ans=ans*b%p;b=b*b%p;y>>=1;}return ans;}
LL ksml(LL x,LL y,int p){LL b=x,ans=1;while(y){if(y&1)ans=ans*b%p;b=b*b%p;y>>=1;}return ans;}
il void update(int x){
    for(int i=1;i<=4;i++)
        for(int j=0;j<p[i];j++)
            t[x].b[i][j]=t[x<<1|1].b[i][t[x<<1].b[i][j]%p[i]];
}
void build(int x,int l,int r){
    if(l==r){
        for(int i=1;i<=4;i++){
            for(int j=0;j<p[i];j++){
                if(q[l].ch==‘+‘)t[x].b[i][j]=(j+q[l].a%p[i])%p[i];
                if(q[l].ch==‘-‘)t[x].b[i][j]=(j-q[l].a%p[i]+p[i])%p[i];
                if(q[l].ch==‘*‘)t[x].b[i][j]=q[l].a%p[i]*j%p[i];
                if(q[l].ch==‘^‘)t[x].b[i][j]=ksm(j,q[l].a,p[i])%p[i];
            }
        }
        return;
    }int mid=(l+r)>>1;
    build(x<<1,l,mid);build(x<<1|1,mid+1,r);
    update(x);
}
void change(int x,int l,int r,int pos){
    if(l==r){
        for(int i=1;i<=4;i++)
            for(int j=0;j<p[i];j++){
                if(q[l].ch==‘+‘)t[x].b[i][j]=(j+q[l].a%p[i])%p[i];
                if(q[l].ch==‘-‘)t[x].b[i][j]=(j-q[l].a%p[i]+p[i])%p[i];
                if(q[l].ch==‘*‘)t[x].b[i][j]=q[l].a%p[i]*j%p[i];
                if(q[l].ch==‘^‘)t[x].b[i][j]=ksm(j,q[l].a,p[i]);
            }return;
    }int mid=(l+r)>>1;
    if(pos<=mid)change(x<<1,l,mid,pos);
    else change(x<<1|1,mid+1,r,pos);
    update(x);
}
int main()
{
  n=read();m=read();
  for(int i=1;i<=n;i++){cin>>q[i].ch;q[i].a=read();}
  build(1,1,n);for(int i=1;i<=4;i++)k[i]=ksml((LL)(P/p[i]),(LL)(p[i]-2),p[i]);
  for(int i=1;i<=m;i++){
    int op=read();int x,y;
    if(op==1){
          x=read();cout<<s[t[1].b[3][x%17]%17];LL ans=0;
          for(int i=1;i<=4;i++){ans=(ans+(LL)t[1].b[i][x%p[i]]*(LL)k[i]%P*(LL)(P/p[i])%P)%P;}
          printf(" %d\n",ans);
        }
        else{x=read();cin>>q[x].ch;q[x].a=read();change(1,1,n,x);}
    }
  return 0;
}

原文地址:https://www.cnblogs.com/Jessie-/p/9440110.html

时间: 2024-08-29 13:46:57

暑假集训8.7数据结构专题-很妙的线段树( 觉醒力量(hidpower))的相关文章

暑假集训8.7数据结构专题-线段树存直线

题目: E-card oj1811 思路:线段树内存直线的k和b,线段树存x,当某个区间的左右端点代入关系始终严格优于或劣于带修改的值,则修改区间.否则继续分散到两个子区间重复操作. 代码: #include<bits/stdc++.h> #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=100005; struct node{int l,r,a,

数据结构(括号序列,线段树):ZJOI 2007 捉迷藏

[题目描述] Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达. 游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯.在起初的时候,所有的灯都没有被打开.每一次,孩子们只会躲 藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯.为了评估某一次

COJ 0358 xjr考考你数据结构(根号3)线段树区间修改

xjr考考你数据结构(根号3) 难度级别:C: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你编写一个数据结构,完成以下功能: 1)求出第L个到第R个数中的最大.最小值以及连续和. 2)将第addL到addR个数改成v. 输入 第一行:n,表示数的个数第二行:空格分开每个数Ai第三行:Q,表示操作数目后Q行:先输入一个字母,       若字母为“Q”则后面跟上两个数,分别为L与R       若字母为“C”则后面跟上三个数,分别为a

COJ 0359 xjr考考你数据结构(根号2)线段树区间增加

xjr考考你数据结构(根号2) 难度级别:C: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你编写一个数据结构,完成以下功能: 1)求出第L个到第R个数中的最大.最小值以及连续和. 2)将第addL到addR个数增加v. 输入 第一行:n,表示数的个数第二行:空格分开每个数Ai第三行:Q,表示操作数目后Q行:先输入一个字母,       若字母为“Q”则后面跟上两个数,分别为L与R       若字母为“A”则后面跟上三个数,分别为a

暑假集训day7

从今天开始,进入数据结构专场. 今天讲线段树. 第一题就好丧,调了快一天. LA 3938 好像没什么可说的,就是细节比较多罢了 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int maxn=500010; inline int read(){ int t=1,num=0;char c=getchar(

【算法导论】第十一课 扩充的数据结构、动态有序统计和区间树

本节课主要讲了如何构造自己想要的数据结构,或者扩充已有数据结构的功能,以实现想要的特定功能 比如设计一个动态结构,满足功能寻找第k大的数 其做法是维护每个结点的子结点个数来推导其秩,而不维护其秩,因为动态操作会使得其难以维护 红黑树的插入操作 1.树插入 2.rebalance 构造自己需要的扩充数据结构的基本流程 1.选择一个基本的数据结构 例如红黑树 2.决定要添加到结点的基本信息  例如实现查询第k大数功能,应添加的基本信息为所有子树结点之和,而非直接保存该结点键值的秩 3 维持 插入+旋

hdu 5289 关于线段树的解法 很有意思

欢迎参加--BestCoder周年纪念赛(高质量题目+多重奖励) Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1565    Accepted Submission(s): 754 Problem Description Tom owns a company and he is the boss. There

2014 UESTC暑前集训数据结构专题解题报告

A.Islands 这种联通块的问题一看就知道是并查集的思想. 做法:从高水位到低水位依序进行操作,这样每次都有新的块浮出水面,可以在前面的基础上进行合并集合的操作.给每个位置分配一个数字,方便合并集合.同时将这些数字也排一个序,降低枚举的复杂度.合并集合时向四周查询浮出水面但是没有合并到同一集合的点进行合并. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath&

暑假集训之专题----拓扑排序题解

第一单: Problem A Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 26   Accepted Submission(s) : 5 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is so h