【解题报告】2017-2018 8th BSUIR Open Programming Contest-C Good subset 线性基+线段树
生活随笔
收集整理的這篇文章主要介紹了
【解题报告】2017-2018 8th BSUIR Open Programming Contest-C Good subset 线性基+线段树
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
2017-2018 8th BSUIR Open Programming Contest. Semifinal C題Good subset.
訓(xùn)練上做了三個小時硬肝出來,先寫的trie,然后知道鐵用線性基,線性基考場現(xiàn)學(xué)真刺激hhh
大概題意是n個操作,每個操作往隊列隊尾加一個數(shù)(x屬于[0,42]),或者刪掉隊首的數(shù),每次操作輸出能否在已有的數(shù)中選出若干個數(shù)求得異或和為42
思路:離線操作,時間做區(qū)間用線段樹維護每個時間點的線性基,從而就避免了線性基的刪除操作。但感覺不是正解???
線性基的d不能開太大,會卡空間,還有maxn也是。
明天學(xué)線性基和高斯消元
線性基板子參考:https://blog.csdn.net/baodream/article/details/83025285
AC代碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+7; struct L_B{int d[8];L_B(){memset(d,0,sizeof(d));}bool insert(int val){for (int i=7;i>=0;i--)if (val&(1<<i)){if (!d[i]){d[i]=val;break;}val^=d[i];}return val>0;}void clear(){memset(d,0,sizeof(d));} }; L_B merge(const L_B &n1,const L_B &n2) {L_B ret=n1;for (int i=7;i>=0;i--)if (n2.d[i])ret.insert(n2.d[i]);return ret; } struct node{L_B xxj;int left,right;bool tag_judge;L_B tag; }tree[maxn<<2]; struct lx{int tL,tR;int num;lx(int _tL,int _tR,int _num){tL=_tL;tR=_tR;num=_num;} }; vector<lx> a; void build(int root,int left,int right) {tree[root].left=left,tree[root].right=right;tree[root].tag_judge=false;if(left==right){return;}int mid=(left+right)>>1;build(root<<1,left,mid);build(root<<1|1,mid+1,right); } void pushdown(int root) {if(!tree[root].tag_judge) return;tree[root<<1].tag=merge(tree[root<<1].tag,tree[root].tag),tree[root<<1].tag_judge=true;tree[root<<1].xxj=merge(tree[root<<1].xxj,tree[root].tag);tree[root<<1|1].tag=merge(tree[root<<1|1].tag,tree[root].tag),tree[root<<1|1].tag_judge=true;tree[root<<1|1].xxj=merge(tree[root<<1|1].xxj,tree[root].tag);tree[root].tag.clear(); tree[root].tag_judge=false; } void add(int root,int left,int right,int k) {if(tree[root].left>=left && tree[root].right<=right){tree[root].xxj.insert(k);tree[root].tag.insert(k);tree[root].tag_judge=true;return;}pushdown(root);if(tree[root<<1].right>=left) add(root<<1,left,right,k);if(tree[root<<1|1].left<=right) add(root<<1|1,left,right,k);tree[root].xxj=merge(tree[root<<1].xxj,tree[root<<1|1].xxj); } L_B search(int root,int left,int right) {if(tree[root].left>=left&&tree[root].right<=right) return tree[root].xxj;pushdown(root);L_B sum;sum.clear();if(tree[root<<1].right>=left) sum=merge(sum,search(root<<1,left,right));if(tree[root<<1|1].left<=right) sum=merge(sum,search(root<<1|1,left,right));return sum; } void init() {a.clear();for(int i=0;i<maxn<<2;i++){tree[i].xxj.clear();} } int main() {int n;while(cin>>n){init();queue<int> q; while(!q.empty()) q.pop();queue<int> q2; while(!q2.empty()) q2.pop();char s[5];int num;int start;for(int i=1;i<=n;i++){scanf("%s",s);if(s[0]=='+'){scanf("%d",&num);q.push(num);q2.push(i);}else{num=q.front();q.pop();start=q2.front();q2.pop();a.push_back(lx(start,i-1,num));}}while(!q.empty()){num=q.front(),q.pop();start=q2.front(),q2.pop();a.push_back(lx(start,n,num));}build(1,1,n);for(int i=0;i<a.size();i++){add(1,a[i].tL,a[i].tR,a[i].num);}for(int i=1;i<=n;i++){L_B temp=search(1,i,i);if(temp.insert(42)) printf("No\n");else printf("Yes\n");} }return 0; }總結(jié)
以上是生活随笔為你收集整理的【解题报告】2017-2018 8th BSUIR Open Programming Contest-C Good subset 线性基+线段树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 博客中GIF动画超简单制作
- 下一篇: 记录:win10 cmd切换目录 切