【题目】: \color{blue}{\text{【题目】:}} 【题目】: 你有一个数 x x x,初始为 1 1 1。你有两种操作,分别为:
【思路】: \color{blue}{\text{【思路】:}} 【思路】: 直接模拟会因为爆 long long
的问题导致代码非常复杂,甚至无法编写。
考虑强大的数据结构——线段树。建立一棵线段树,其叶子节点都是对于的乘数,每个非叶子节点的值为其左右儿子的值的乘积对 mod \text{mod} mod 取模的值。这样,任意时候都有 x = x= x= 该线段树的根的值。
操作 1 1 1 可以直接上,操作 2 2 2 可以看做是把第 t t t 次的乘数改为 1 1 1。因此,我们只需要打一个线段树修改即可。
【 代 码 】 : \color{blue}{【代码】:} 【代码】:
const int N=1e5+100;
#define ll long long
ll mod;int tot,G[N];
int test_number,q;
struct Segment_tree{
ll sum[N<<2];//记得4倍空间
inline void pushup(int o){
sum[o]=sum[o<<1]*sum[o<<1|1]%mod;
}
inline void build(int o,int l,int r){
if (l==r){sum[o]=1ll;return;}
register int mid=(l+r)>>1;
build(o<<1|1,mid+1,r);
build(o<<1,l,mid);
pushup(o);return;
}
void updata(int o,int l,int r,int p,ll v){
if (l==r){sum[o]=v;return;}
register int mid=(l+r)>>1;
if (p<=mid) updata(o<<1,l,mid,p,v);
else updata(o<<1|1,mid+1,r,p,v);
pushup(o);return;
}
}SGT;
#define gc getchar()
#define g(c) isdigit(c)
inline ll read(){
char c=0;ll x=0;bool f=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
namespace fast_write{
void write(ll a,bool b){
if (a==0){
if (b) putchar('0');
}
else{
write(a/10,false);
putchar(a%10+'0');
}
}
void print(ll a,char c){
write(a,true);
putchar(c);
}
}
int main(){
test_number=read();
while (test_number--){
q=read();mod=read();
SGT.build(1,1,q);tot=0;
memset(G,0,sizeof(G));
for(int i=1;i<=q;i++){
int opt=read();ll t=read();
if (opt==2) SGT.updata(1,1,q,G[t],1);
else SGT.updata(1,1,q,G[i]=(++tot),t%mod);
fast_write::print(SGT.sum[1]%mod,'\n');
}
}
return 0;
}
【 链 接 】 : \color{blue}{【链接】:} 【链接】: https://www.luogu.com.cn/problem/P1575
【 思 路 】 : \color{blue}{【思路】:} 【思路】: 很简单,直接用一个栈模拟即可。如果 not
后面不是 true
或 false
的话,就输出 error
。
#include
using namespace std;
stack<bool> num;
stack<string> oper;
int cti(string s){
if (s=="or") return 1;
if (s=="and") return 2;
if (s=="not") return 3;
return 0;
}
inline bool calc(){
register bool x,y;
if (num.size()){
y=num.top();num.pop();
}
else return false;
if (num.size()){
x=num.top();num.pop();
}
else return false;
string c=oper.top();oper.pop();
if (c=="and") num.push(x&&y);
else num.push(x||y);
return true;
}
bool Not(string s){
if (s=="true") return 0;
if (s=="false") return 1;
}
string s;bool flag;
int main(){
getline(cin,s);
stringstream ss(s);
while (ss>>s){
if (s=="not"){
if (ss>>s){
if (s!="true"&&s!="false"){
printf("error");
return 0;
}
else num.push(Not(s));
}
else{
printf("error");
return 0;
}
flag=false;
}
else if (cti(s)){
if (num.empty()){
printf("error");
return 0;
}
while (oper.size()&&cti(oper.top())>=cti(s)){
if (!calc()){
printf("error");
return 0;
}
}
oper.push(s);
flag=false;
}
else{
if (flag){
printf("error");
return 0;
}
num.push(!Not(s));
flag=true;
}
}
while (oper.size()){
if (!calc()){
printf("error");
return 0;
}
}
if (num.size()!=1){
printf("error");
return 0;
}
if (num.top()) printf("true");
else printf("false");
return 0;
}
可是,这样真的就 AC
了吗?不是,有 1 1 1 个点错了。为什么?
因为数据中有如这样的情况 not not true
,这种情况下我们的程序会输出 error
,但是它实际上是应该输出 true
的。我们特殊处理即可。
#include
using namespace std;
stack<bool> num;
stack<string> oper;
int cti(string s){
if (s=="or") return 1;
if (s=="and") return 2;
if (s=="not") return 3;
return 0;
}
inline bool calc(){
register bool x,y;
if (num.size()){
y=num.top();num.pop();
}
else return false;
if (num.size()){
x=num.top();num.pop();
}
else return false;
string c=oper.top();oper.pop();
if (c=="and") num.push(x&&y);
else num.push(x||y);
return true;
}
inline bool Not(string s){
if (s=="true") return 0;
else return 1;
}
string s;bool flag,sign;
int main(){
getline(cin,s);
stringstream ss(s);
while (ss>>s){
if (s=="not"){
if (ss>>s){
if (s!="true"&&s!="false"&&s!="not"){
printf("error");
return 0;
}
if (s=="true"||s=="false")
num.push(Not(s));
else{
sign=false;
while (ss>>s){
if (s!="true"&&s!="false"&&s!="not"){
printf("error");
return 0;
}
else{
if (s=="not") sign=!sign;
else{
num.push(sign?Not(s):!Not(s));
break;
}
}
}
}
}
else{
printf("error");
return 0;
}
flag=false;
}
else if (cti(s)){
if (num.empty()){
printf("error");
return 0;
}
while (oper.size()&&cti(oper.top())>=cti(s)){
if (!calc()){
printf("error");
return 0;
}
}
oper.push(s);
flag=false;
}
else{
if (flag){
printf("error");
return 0;
}
num.push(!Not(s));
flag=true;
}
}
while (oper.size()){
if (!calc()){
printf("error");
return 0;
}
}
if (num.size()!=1){
printf("error");
return 0;
}
if (num.top()) printf("true");
else printf("false");
return 0;
}
/*
注意!需要特殊判断如not not true这样的情况,
否则无法通过第七个测试点
*/
这提示我们,只有全面的思考,才能获得高分或者 AC
!